pourquoi le conte folklorique et la ramda sont-ils si différents?


96

J'apprends javascript FP en lisant le livre de DrBoolean .

J'ai cherché une bibliothèque de programmation fonctionnelle. J'ai trouvé Ramda et Folktale. Les deux prétendent être une bibliothèque de programmation fonctionnelle.

Mais ils sont si différents:

  • Ramda semble contenir des fonctions utilitaires pour gérer la liste: mapper, réduire, filtrer et des fonctions pures: curry, composer. Il ne contient rien concernant la monade, le foncteur.

  • Folktale ne contient cependant aucun utilitaire pour la liste ou les fonctions. Il semble implémenter certaines structures algébriques en javascript comme monad: Peut-être, tâche ...

En fait, j'ai trouvé plus de bibliothèques, elles semblent toutes tomber dans les deux catégories. Underscore et lodash sont comme Ramda. Fantasy-land, pointfree-fantasy sont comme des contes populaires.

Ces bibliothèques très différentes peuvent-elles être qualifiées de fonctionnelles , et si oui, qu'est-ce qui fait de chacune d'elles une bibliothèque fonctionnelle?


1
utilisez ce qui correspond à vos besoins et à votre style et est bien documenté
charlietfl

1
J'ai trouvé qu'il y a vraiment trois significations communément destinées à la "programmation fonctionnelle", en particulier dans JS. 1. en utilisant des fonctions pures d'ordre supérieur sur des ensembles tels que des tableaux., Ex [1,2,3].map(fnSquare).reduce(fnSum)2. en grande partie académique "look ma no var " Y-combinator-esque structures. 3. utiliser Function.prototypepour modifier le comportement d'autres fonctions, commevar isMissingID=fnContains.partial("id").negate();
dandavis

10
Un auteur Ramda ici: Ramda est une bibliothèque utilitaire de bas niveau. Il est destiné à simplifier un certain style fonctionnel dans JS, en particulier en travaillant en composant des fonctions. Ramda fonctionne bien avec la spécification FantasyLand, y compris ses implémentations telles que Folktale. Ces bibliothèques sont conçues dans un but quelque peu différent. Ils sont construits autour de la reconnaissance des types de données abstraits courants et de leur permettre un accès cohérent: des éléments tels que les monoïdes, les fonctions et les monades. Ramda travaillera avec eux et a un projet parallèle pour en créer, mais c'est, comme vous le dites, un objectif très différent.
Scott Sauyet

1
@KeithNicholas: Oui, il y a une Gitter Room
Scott Sauyet

2
Jetez également un œil à Sanctuary - github.com/plaid/sanctuary Ceci est basé sur ramda mais couvre également les types de terres fantastiques.
arcseldon

Réponses:


180

Caractéristiques fonctionnelles

Il n'y a pas de limite claire de ce qui définit la programmation fonctionnelle ou une bibliothèque fonctionnelle. Certaines fonctionnalités des langages fonctionnels sont intégrées à Javascript:

  • Fonctions de premier ordre et d'ordre supérieur
  • Fonctions Lambdas / Anonymes, avec fermetures

D'autres sont possibles à réaliser en Javascript avec un certain soin:

  • Immutabilité
  • Transparence référentielle

D'autres encore font partie d'ES6 et sont partiellement ou entièrement disponibles pour le moment:

  • Fonctions compactes, voire concises
  • Récursivité performante grâce à l'optimisation des appels de fin

Et il y en a beaucoup d'autres qui sont vraiment hors de portée normale de Javascript:

  • Correspondance de motif
  • Évaluation paresseuse
  • Homoiconicité

Une bibliothèque, alors, peut choisir les types de fonctionnalités qu'elle essaie de prendre en charge et toujours raisonnablement qualifiée de "fonctionnelle".

Spécification Fantasy-Land

Fantasy-terre est une spécification pour un certain nombre de types standards portés de la catégorie mathématique et théorie abstraite algèbre à la programmation fonctionnelle, types tels que Monoid , Functor et Monad . Ces types sont assez abstraits et étendent peut-être des notions plus familières. Les foncteurs, par exemple, sont des conteneurs qui peuvent être mappédalés avec une fonction, comme un tableau peut être mappédalé en utilisant Array.prototype.map.

Conte folklorique

Folktale est une collection de types mettant en œuvre diverses parties de la spécification Fantasy-land et une petite collection de fonctions utilitaires complémentaires. Ces types sont des choses comme Peut - être , l'un ou l'autre , une tâche (très similaire à ce qu'on appelle ailleurs un avenir, et un cousin plus légitime d'une promesse), et la validation

Folktale est peut-être l'implémentation la plus connue de la spécification Fantasy-land, et elle est très respectée. Mais il n'existe pas d'implémentation définitive ou par défaut; fantasy-land ne spécifie que des types abstraits, et une implémentation doit bien sûr créer de tels types concrets. La prétention de Folktale d'être une bibliothèque fonctionnelle est claire: elle fournit des types de données que l'on trouve généralement dans les langages de programmation fonctionnels, ceux qui facilitent considérablement la programmation de manière fonctionnelle.

Cet exemple, tiré de la documentation Folktale ( note : pas dans les versions récentes de la documentation), montre comment il pourrait être utilisé:

// We load the library by "require"-ing it
var Maybe = require('data.maybe')

// Returns Maybe.Just(x) if some `x` passes the predicate test
// Otherwise returns Maybe.Nothing()
function find(predicate, xs) {
  return xs.reduce(function(result, x) {
    return result.orElse(function() {
      return predicate(x)?    Maybe.Just(x)
      :      /* otherwise */  Maybe.Nothing()
    })
  }, Maybe.Nothing())
}

var numbers = [1, 2, 3, 4, 5]

var anyGreaterThan2 = find(function(a) { return a > 2 }, numbers)
// => Maybe.Just(3)

var anyGreaterThan8 = find(function(a) { return a > 8 }, numbers)
// => Maybe.Nothing

Ramda

Ramda (avertissement: je suis l'un des auteurs) est un type de bibliothèque très différent. Il ne fournit pas de nouveaux types pour vous. 1 Au lieu de cela, il fournit des fonctions pour faciliter l'utilisation des types existants. Il est construit autour des notions de composition de fonctions plus petites en fonctions plus grandes, de travail avec des données immuables, d'éviter les effets secondaires.

Ramda opère surtout sur les listes, mais aussi sur les objets, et parfois sur les chaînes. Il délègue également plusieurs de ses appels de manière à interagir avec Folktale ou d'autres implémentations Fantasy-land. Par exemple, la mapfonction de Ramda fonctionne de la même manière que celle sur Array.prototype, donc R.map(square, [1, 2, 3, 4]); //=> [1, 4, 9, 16]. Mais comme Folktale Maybeimplémente la Functorspécification Fantasy-land , qui spécifie également la carte, vous pouvez également utiliser Ramda mapavec:

R.map(square, Maybe.Just(5)); //=> Maybe.Just(25);
R.map(square, Maybe.Nothing); //=> Maybe.Nothing

Les prétentions de Ramda à être une bibliothèque fonctionnelle consistent à faciliter la composition de fonctions, à ne jamais muter vos données et à ne présenter que des fonctions pures. L'utilisation typique de Ramda serait de construire des fonctions plus complexes en composant des plus petites, comme on le voit dans un article sur la philosophie de Ramda

// :: [Comment] -> [Number]  
var userRatingForComments = R.pipe(
    R.pluck('username')      // [Comment] -> [String]
    R.map(R.propOf(users)),  // [String] -> [User]
    R.pluck('rating'),       // [User] -> [Number]
);

Autres bibliothèques

En fait, j'ai trouvé plus de bibliothèques, elles semblent toutes tomber dans les deux catégories. soulignement, lodash est très similaire à Ramda. Fantasy-land, pointfree-fantasy sont comme des contes populaires.

Ce n'est pas vraiment exact. Tout d'abord, Fantasy-land est simplement une spécification que les bibliothèques peuvent décider d'implémenter pour différents types. Folktale est l'une des nombreuses implémentations de cette spécification, probablement la meilleure, certainement l'une des plus matures. Pointfree-fantasy et ramda-fantasy en sont d'autres, et il y en a bien d'autres .

Underscore et lodash sont superficiellement comme Ramda en ce qu'ils sont des bibliothèques à saisir, fournissant un grand nombre de fonctions avec beaucoup moins de cohésion que quelque chose comme Folktale. Et même la fonctionnalité spécifique chevauche souvent celle de Ramda. Mais à un niveau plus profond, Ramda a des préoccupations très différentes de celles de ces bibliothèques. Cousins les plus proches de Ramda sont probablement des bibliothèques comme Fkit , FNUC et Wu.js .

Bilby est dans une catégorie à part, fournissant à la fois un certain nombre d'outils tels que ceux fournis par Ramda et certains types compatibles avec Fantasy-land. (L'auteur de Bilby est également l'auteur original de Fantasy-land.)

Ton appel

Toutes ces bibliothèques ont le droit d'être qualifiées de fonctionnelles, même si leur approche fonctionnelle et leur degré d'engagement fonctionnel varient considérablement.

Certaines de ces bibliothèques fonctionnent en fait bien ensemble. Ramda devrait bien fonctionner avec Folktale ou d'autres implémentations Fantasy-land. Étant donné que leurs préoccupations se chevauchent à peine, elles ne sont vraiment pas en conflit, mais Ramda en fait juste assez pour rendre l'interopération relativement fluide. C'est probablement moins vrai pour certaines des autres combinaisons que vous pourriez choisir, mais la syntaxe de fonction plus simple d'ES6 peut également soulager une partie de la douleur de l'intégration.

Le choix de la bibliothèque, voire du style de bibliothèque à utiliser, dépendra de votre projet et de vos préférences. Il existe de nombreuses options intéressantes, et les chiffres augmentent, et bon nombre d'entre elles s'améliorent considérablement. C'est le bon moment pour faire de la programmation fonctionnelle dans JS.


1 Eh bien, il y a un projet parallèle , ramda-fantasy qui fait quelque chose de similaire à ce que fait Folktale, mais il ne fait pas partie de la bibliothèque principale.


1
Serait-il juste de dire que ES6 a la capacité d'une évaluation paresseuse avec l'introduction de Yield? developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
Marcel Lamothe

8
Non, yieldil est plus facile d'effectuer les types de traitement de liste paresseux effectués par Lazyou lz.js. Mais cela n'aide pas à la paresse au niveau de la langue. someFunc(a + b)dans JS ajoute d'abord les valeurs de a, bpuis fournit ce résultat comme paramètre à someFunc. L'équivalent en Haskell ne fait pas cela. Si la fonction appelée n'utilise jamais cette valeur, elle n'effectue jamais l'addition. S'il l'utilise finalement, il est considéré comme une expression à calculer jusqu'à ce que son résultat soit nécessaire. Si vous ne faites jamais quoi que ce soit qui le forcera (comme IO), il n'effectuera jamais le calcul.
Scott Sauyet

@ScottSauyet vous pourriez peut-être dire que "l'évaluation paresseuse" sous une forme ou une autre est disponible via les générateurs ES6 par exemple - beaucoup de frameworks JS ont des caractéristiques de "paresse" - RxJs, ImmutableJs etc.
arcseldon

8
Cette réponse devrait être un chapitre ou une section du livre de DrBoolean. :)
Seth

1
La documentation Ramda a tendance à utiliser "liste" comme raccourci pour ce que JS offre le plus proche des listes, des tableaux denses. Celles-ci ont des caractéristiques de performances différentes de celles des listes pures, et bien sûr une API quelque peu différente, mais elles peuvent être utilisées à peu près aux mêmes fins, et elles sont le type natif le plus proche (mais voir github.com/funkia/list ) disponible pour Ramda. API, qui souhaite théoriquement travailler avec des listes pures. Je dirais que ce n'est pas le cas des tableaux de vrais tableaux, car les tableaux de style C ne sont pas plus canoniques que ceux de JS, et aucun n'est vraiment proche des tableaux mathématiques, mais c'est un point mineur.
Scott Sauyet
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.