Co to jest styl „bez punktów” (w programowaniu funkcjonalnym)?

103

Zwrot, który ostatnio zauważyłem, to pojęcie stylu „bez punktów” ...

Najpierw było to pytanie, a także to .

Potem odkryłem , że piszą tutaj: „Innym tematem, który warto omówić, jest niechęć autorów do stylu bez punktów”.

Co to jest styl „bez punktów”? Czy ktoś może podać zwięzłe wyjaśnienie? Czy ma to coś wspólnego z „automatycznym” curry?

Aby poznać mój poziom - uczyłem się Schematu i napisałem prostego tłumacza Schematu ... Rozumiem, co to jest „ukryte” curry, ale nie znam żadnego Haskella ani ML.

Paul Hollingsworth
źródło
3
Uwaga: aby zobaczyć, dlaczego nazywa się to pointfree, odwiedź Pointfree / Ale pointfree ma więcej punktów! w HaskellWiki.
Petr Pudlák

Odpowiedzi:

66

Wystarczy spojrzeć na artykuł w Wikipedii, aby uzyskać definicję:

Programowanie ciche (programowanie bez punktów) to paradygmat programowania, w którym definicja funkcji nie zawiera informacji dotyczących jej argumentów, używając kombinatorów i kompozycji funkcji [...] zamiast zmiennych.

Przykład Haskella:

Konwencjonalne (jawnie określasz argumenty):

sum (x:xs) = x + (sum xs)
sum [] = 0

Bez punktów ( sumnie ma żadnych jawnych argumentów - to po prostu fałd +zaczynający się od 0):

 sum = foldr (+) 0

Albo jeszcze prościej: zamiast tego g(x) = f(x)możesz po prostu pisać g = f.

Więc tak: jest to ściśle związane z curry (lub operacjami takimi jak kompozycja funkcji).

Dario
źródło
8
Ahh rozumiem! Więc tworzysz nowe funkcje zawsze po prostu łącząc inne funkcje, zamiast deklarować argumenty ... Bardzo eleganckie!
Paul Hollingsworth,
22
Naprawdę nie lubię wymyślać nowych nazw zmiennych / argumentów podczas programowania. To jeden z głównych powodów, dla których uwielbiam styl bez punktów!
Martijn
2
W jakim sensie ma to związek z curry?
kaleidic
1
@kaleidic: Ponieważ nie mając nazw zmiennych, musisz komponować częściowo zastosowane funkcje. To właśnie nazywamy curry (a dokładniej to, co jest możliwe dzięki curry)
Dario
1
Czy nie masz na myśli sum (x:xs) ...zamiast sum sum (x:xs) ...?
Ehtesh Choudhury,
33

Styl bez punktów oznacza, że ​​argumenty definiowanej funkcji nie są wyraźnie wymienione, że funkcja jest definiowana poprzez kompozycję funkcji.

Jeśli masz dwie funkcje, na przykład

square :: a -> a
square x = x*x

inc :: a -> a
inc x = x+1

a jeśli chcesz połączyć te dwie funkcje w jedną, która oblicza x*x+1, możesz zdefiniować ją jako „punktową” w następujący sposób:

f :: a -> a
f x = inc (square x)

Bezcelową alternatywą byłoby nie mówić o argumentacji x:

f :: a -> a
f = inc . square
sth
źródło
22
Głupio, w Haskell sposób „bez punktów” jest zwykle tym, który wygląda bardziej konkretnie (więcej kropek). Ta irytacja stanowi doskonały mnemonik. (Książka Real World Haskell komentuje to.)
Dan
3
Jeśli chodzi o komentarz @ Dana, strona Pointfree HaskellWiki zawiera wyjaśnienie, dlaczego jest nazywana bez punktów .
Vincent Savard
2
@Dan: Nie wydaje mi się, żeby to było głupie, ponieważ punkt Haskella ma być "tym operatorem okręgu" (chociaż powinien bardziej przypominać °). Jest to jednak mylące, zwłaszcza gdy jesteś nowy w funkcjonalnych językach programowania; każda książka wprowadzająca do haskell powinna wyjaśniać styl bez punktów.
Sebastian Mach
13

Przykład JavaScript:

//not pointfree cause we receive args
var initials = function(name) {
  return name.split(' ').map(compose(toUpperCase, head)).join('. ');
};

const compose = (...fns) => (...args) => fns.reduceRight((res, fn) => [fn.call(null, ...res)], args)[0];
const join = m => m.join();

//pointfree
var initials = compose(join('. '), map(compose(toUpperCase, head)), split(' '));

initials("hunter stockton thompson");
// 'H. S. T'

Odniesienie

Brunno
źródło
5

Styl bez punktów oznacza, że ​​kod nie wymienia wprost swoich argumentów, mimo że istnieją i są używane.

Działa to w Haskell ze względu na sposób działania funkcji.

Na przykład:

myTake = take

zwraca funkcję, która przyjmuje jeden argument, dlatego nie ma powodu, aby jawnie wpisywać argument, chyba że po prostu chcesz.

Rayne
źródło
1
Czasami nie działa w Haskell 98, jak w myShow = show. Więcej na ten temat można znaleźć na wiki Haskell
Ehtesh Choudhury,
-1

Oto jeden przykład w TypeScript bez żadnej innej biblioteki:

interface Transaction {
  amount: number;
}

class Test {
  public getPositiveNumbers(transactions: Transaction[]) {
    return transactions.filter(this.isPositive);

    //return transactions.filter((transaction: {amount: number} => transaction.amount > 0));
  }

  public getBigNumbers(transactions: Transaction[]) {
    // point-free
    return transactions.filter(this.moreThan(10));

    // not point-free
    // return transactions.filter((transaction: any) => transaction.amount > 10);
  }

  private isPositive(transaction: Transaction) {
    return transactions.amount > 0;
  }

  private moreThan(amount: number) {
    return (transaction: Transaction) => {
      return transactions.amount > amount;
    }
  }
}

Jak widać, styl bez punktów jest bardziej „płynny” i łatwiejszy do odczytania.

AZ.
źródło
To nie jest styl bez punktów, to po prostu rozróżnienie między lambdą a nazwaną funkcją.
kralyk
@kralyk Myślę, że przegapiłeś punkt, this.moreThan(10)nie jest to nazwana funkcja, jest to funkcja curried, a także funkcja, która domyślnie (a zatem bez punktu) przyjmie a transactionjako dane wejściowe.
AZ.