Qu'est-ce que le style «sans point» (en programmation fonctionnelle)?

101

Une phrase que j'ai remarquée récemment est le concept de style "sans point" ...

Il y avait d'abord cette question, et aussi celle-ci .

Ensuite, j'ai découvert ici qu'ils mentionnent «Un autre sujet qui mérite d'être discuté est l'aversion des auteurs pour le style sans point».

Qu'est-ce que le style «sans point»? Quelqu'un peut-il donner une explication concise? Cela a-t-il quelque chose à voir avec le curry "automatique"?

Pour avoir une idée de mon niveau - je me suis enseigné le Scheme et j'ai écrit un simple interpréteur de Scheme ... Je comprends ce qu'est le curry "implicite", mais je ne connais aucun Haskell ou ML.

Paul Hollingsworth
la source
3
Juste une note: pour voir pourquoi cela s'appelle pointfree visitez Pointfree / Mais pointfree a plus de points! à HaskellWiki.
Petr Pudlák le

Réponses:

66

Regardez simplement l'article Wikipédia pour obtenir votre définition:

La programmation tacite (programmation sans point) est un paradigme de programmation dans lequel une définition de fonction n'inclut pas d'informations concernant ses arguments, utilisant des combinateurs et une composition de [...] fonction au lieu de variables.

Exemple Haskell:

Conventionnel (vous spécifiez les arguments explicitement):

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

sumSans point ( n'a pas d'arguments explicites - c'est juste un pli +commençant par 0):

 sum = foldr (+) 0

Ou encore plus simple: au lieu de g(x) = f(x), vous pouvez simplement écrire g = f.

Alors oui: c'est étroitement lié au curry (ou à des opérations comme la composition de fonctions).

Dario
la source
8
Ahh je vois! Vous construisez donc de nouvelles fonctions toujours juste en combinant d'autres fonctions plutôt qu'en déclarant des arguments ... Très élégant!
Paul Hollingsworth
22
Je n'aime vraiment pas avoir à trouver de nouveaux noms pour les variables / arguments lorsque je programme. C'est l'une des principales raisons pour lesquelles j'aime le style sans point!
Martijn
2
De quelle manière est-il lié au curry?
kaleidic
1
@kaleidic: Parce que sans avoir de noms de variables, vous devez composer des fonctions partiellement appliquées. C'est ce que nous appelons le curry (ou, plus précisément, ce qui est rendu possible grâce au curry)
Dario
1
Tu ne veux pas dire sum (x:xs) ...au lieu de sum sum (x:xs) ...?
Ehtesh Choudhury
33

Le style sans point signifie que les arguments de la fonction définie ne sont pas explicitement mentionnés, que la fonction est définie par la composition de la fonction.

Si vous avez deux fonctions, comme

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

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

et si vous voulez combiner ces deux fonctions en une qui calcule x*x+1, vous pouvez le définir "point-plein" comme ceci:

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

L'alternative sans point serait de ne pas parler de l'argument x:

f :: a -> a
f = inc . square
qc
la source
22
Stupidement, chez Haskell, la méthode «sans point» est généralement celle qui semble la plus pointue (plus de points). Cette contrariété fait un excellent mnémonique. (Le livre Real World Haskell commente à ce sujet.)
Dan
3
Concernant le commentaire de @ Dan, la page Pointfree HaskellWiki explique pourquoi il est appelé pointfree .
Vincent Savard
2
@Dan: Je ne pense pas que ce soit stupide, car le point Haskell est censé être "cet opérateur de cercle" (il devrait cependant ressembler davantage à °). Mais c'est déroutant, surtout lorsque vous êtes nouveau dans les langages de programmation fonctionnels; chaque livre d'introduction sur haskell devrait expliquer le style sans point.
Sebastian Mach
12

Un exemple 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'

Référence

Brunno
la source
5

Le style sans point signifie que le code ne mentionne pas explicitement ses arguments, même s'ils existent et sont utilisés.

Cela fonctionne dans Haskell en raison du fonctionnement des fonctions.

Par exemple:

myTake = take

renvoie une fonction qui prend un argument, il n'y a donc aucune raison de taper explicitement l'argument sauf si vous le souhaitez.

Rayne
la source
1
Parfois, cela ne fonctionne pas dans Haskell 98, comme dans myShow = show. Il y a plus à ce sujet sur le wiki Haskell
Ehtesh Choudhury
-1

Voici un exemple de TypeScript sans aucune autre bibliothèque:

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;
    }
  }
}

Vous pouvez voir que le style sans point est plus "fluide" et plus facile à lire.

AZ.
la source
Ce n'est pas un style sans point, c'est juste une distinction entre une fonction lambda et une fonction nommée.
kralyk
@kralyk Je pense que vous avez manqué le point, ce this.moreThan(10)n'est pas une fonction nommée, c'est une fonction curry ainsi qu'une fonction qui prendra implicitement (donc sans point) a transactioncomme entrée.
AZ.