web-dev-qa-db-fra.com

Ruby est-il un langage fonctionnel?

Wikipedia dit Ruby est un langage fonctionnel, mais je ne suis pas convaincu. Pourquoi ou pourquoi pas?

87
Esteban Araya

Je pense très certainement que vous pouvez utiliser un style fonctionnel dans Ruby.

L'un des aspects les plus critiques pour pouvoir programmer dans un style fonctionnel est si le langage prend en charge des fonctions d'ordre supérieur ... ce qui Ruby le fait.

Cela dit, il est facile de programmer en Ruby dans un style non fonctionnel également. Un autre aspect clé du style fonctionnel est de ne pas avoir d'état, et d'avoir de vraies fonctions mathématiques qui retournent toujours la même valeur pour un ensemble donné d'entrées. Cela peut être fait en Ruby, mais il n'est pas appliqué dans le langage comme quelque chose de plus strictement fonctionnel comme Haskell.

Donc, oui, il prend en charge le style fonctionnel, mais il vous permettra également de programmer dans un style non fonctionnel.

29
Mike Stone

Qu'une langue soit ou non une langue fonctionnelle n'a pas d'importance. La programmation fonctionnelle est une thèse, mieux expliquée par Philip Wadler (The Essence of Functional Programming) et John Hughes (Why Functional Programming Matters).

Une question significative est: "Dans quelle mesure Ruby est-il prêt à réaliser la thèse de la programmation fonctionnelle?" La réponse est "très mal").

J'ai donné une conférence à ce sujet récemment. Voici les diapositives.

58
Tony Morris

Ruby prend en charge les fonctions de niveau supérieur (voir Array # map, inject, & select), mais c'est toujours un langage impératif orienté objet.

L'une des caractéristiques clés d'un langage fonctionnel est qu'il évite l'état mutable. Les langages fonctionnels n'ont pas le concept d'une variable comme vous l'auriez fait en Ruby, C, Java ou tout autre langage impératif.

Une autre caractéristique clé d'un langage fonctionnel est qu'il se concentre sur la définition d'un programme en termes de "quoi", plutôt que de "comment". Lors de la programmation dans un langage OO, nous écrivons des classes et des méthodes pour cacher l'implémentation (le "comment") du "quoi" (le nom de la classe/méthode), mais à la fin ces méthodes sont toujours écrits à l'aide d'une séquence d'instructions. Dans un langage fonctionnel, vous ne spécifiez pas une séquence d'exécution, même au niveau le plus bas.

34
Mike

Je soumets que soutenir ou avoir la capacité de programmer dans une langue dans un style fonctionnel ne fait pas un langage fonctionnel.

Je peux même écrire Java code dans un style fonctionnel si je veux blesser mes collègues et moi-même quelques-uns mois semaines.

Avoir un langage fonctionnel ne concerne pas seulement ce que vous pouvez faire, comme les fonctions d'ordre supérieur, les fonctions de première classe et le curry. Il s'agit également de ce que vous ne pouvez pas faire, comme les effets secondaires dans les fonctions pures.

Ceci est important car c'est une grande partie de la raison pour laquelle les programmes fonctionnels sont, ou le code fonctionnel en général est, plus facile à raisonner. Et lorsque le code est plus facile à raisonner, les bogues deviennent moins profonds et flottent à la surface conceptuelle où ils peuvent être corrigés, ce qui donne à son tour moins de code bogué.

Ruby est orienté objet dans son cœur, donc même s'il prend raisonnablement bien en charge un style fonctionnel, il n'est pas lui-même un langage fonctionnel.

C'est mon avis non scientifique de toute façon.

Edit: Rétrospectivement et en tenant compte des bons commentaires que j'ai reçus à ce jour jusqu'à présent, je pense que la comparaison orientée objet versus fonctionnelle est celle des pommes et des oranges.

Le véritable différenciateur est celui de l'imparative exécution ou non. Les langages fonctionnels ont l'expression comme construction linguistique principale et l'ordre d'exécution est souvent indéfini ou défini comme étant paresseux. Une exécution stricte est possible mais n'est utilisée qu'en cas de besoin. Dans un langage imparatif, une exécution stricte est la valeur par défaut et bien qu'une exécution paresseuse soit possible, elle est souvent fastidieuse à faire et peut avoir des résultats imprévisibles dans de nombreux cas Edge.

Maintenant, c'est mon avis non scientifique.

16
Chris Vest

Ruby devra répondre aux exigences suivantes pour être fonctionnel "VRAIMENT".

Valeurs immuables: une fois qu'une "variable" est définie, elle ne peut pas être modifiée. Dans Ruby, cela signifie que vous devez effectivement traiter les variables comme des constantes. Le n'est pas entièrement pris en charge dans la langue, vous devrez geler chaque variable manuellement.

Pas d'effets secondaires: lorsqu'elle passe une valeur donnée, une fonction doit toujours retourner le même résultat. Cela va de pair avec des valeurs immuables; une fonction ne peut jamais prendre une valeur et la modifier, car cela provoquerait un effet secondaire tangentiel au retour d'un résultat.

Fonctions d'ordre supérieur: ce sont des fonctions qui autorisent des fonctions comme arguments, ou utilisent des fonctions comme valeur de retour. C'est, sans doute, l'une des caractéristiques les plus critiques de tout langage fonctionnel.

Currying: activé par les fonctions d'ordre supérieur, le curry transforme une fonction qui prend plusieurs arguments en une fonction qui prend un argument. Cela va de pair avec une application de fonction partielle, qui transforme une fonction multi-arguments en une fonction qui prend moins d'arguments qu'elle ne le faisait à l'origine.

Récursion: bouclage en appelant une fonction de l'intérieur de lui-même. Lorsque vous n'avez pas accès aux données modifiables, la récursivité est utilisée pour créer et chaîner la construction des données. En effet, le bouclage n'est pas un concept fonctionnel, car il nécessite le passage de variables pour stocker l'état de la boucle à un instant donné.

Évaluation différée ou évaluation différée: retardant le traitement des valeurs jusqu'au moment où elles sont réellement nécessaires. Si, par exemple, vous avez du code qui a généré une liste de nombres de Fibonacci avec l'évaluation paresseuse activée, cela ne sera pas réellement traité et calculé tant qu'une des valeurs du résultat n'aura pas été requise par une autre fonction, comme put.

Proposition (Juste une pensée) Je serais heureux d'avoir une sorte de définition pour avoir une directive mode pour déclarer des fichiers avec un paradigme fonctionnel, exemple

mode "fonctionnel"

13
Elias Perez

Ruby est un langage multi-paradigmes qui prend en charge un style fonctionnel de programmation.

9
skymt

Ruby est un langage orienté objet, qui peut prendre en charge d'autres paradigmes (fonctionnel, impératif, etc.). Cependant, puisque tout en Ruby est un objet, c'est principalement un langage OO.

exemple:

"bonjour" .reverse () = "olleh", chaque chaîne est une instance d'objet chaîne et ainsi de suite.

Lisez ici ou ici

4
camflan

Cela dépend de votre définition d'un "langage fonctionnel". Personnellement, je pense que le terme lui-même est assez problématique lorsqu'il est utilisé comme un absolu. Il y a plus d'aspects à être un "langage fonctionnel" que de simples fonctionnalités linguistiques et la plupart dépendent de l'endroit d'où vous cherchez. Par exemple, la culture entourant la langue est assez importante à cet égard. Encourage-t-il un style fonctionnel? Qu'en est-il des bibliothèques disponibles? Vous encouragent-ils à les utiliser de manière fonctionnelle?

La plupart des gens appelleraient Scheme un langage fonctionnel, par exemple. Mais qu'en est-il du Common Lisp? Mis à part le problème des espaces de noms multiples/uniques et l'élimination garantie des appels de queue (que certaines implémentations CL prennent également en charge, selon les paramètres du compilateur), il n'y a pas grand-chose qui fait de Scheme un langage plus adapté à la programmation fonctionnelle que Common. LISP, et pourtant, la plupart des Lispers n'appelleraient pas CL un langage fonctionnel. Pourquoi? Parce que la culture qui l'entoure dépend fortement des caractéristiques impératives de CL (comme la macro LOOP, par exemple, que la plupart des Schemers désapprouveraient probablement).

D'un autre côté, un programmeur C peut très bien considérer CL comme un langage fonctionnel. La plupart du code écrit dans n'importe quel dialecte LISP est certainement beaucoup plus fonctionnel dans le style que votre bloc habituel de code C, après tout. De même, Scheme est un langage impératif par rapport à Haskell. Par conséquent, je ne pense pas qu'il puisse jamais y avoir de réponse définitive oui/non. Que ce soit pour appeler une langue fonctionnelle ou non dépend fortement de votre point de vue.

4
Matthias Benkard

La récursivité est courante dans la programmation fonctionnelle. Presque tous les langages prennent en charge la récursivité, mais les algorithmes récursifs sont souvent inefficaces s'il n'y a pas appel de queue optimisation (TCO).

Les langages de programmation fonctionnels sont capables d'optimiser la récursivité de queue et peuvent exécuter un tel code dans un espace constant. Certaines implémentations Ruby optimisent la récursivité de la queue, d'autres non, mais en général Ruby ne sont pas nécessaires pour effectuer le TCO. Voir Ruby effectuer l'optimisation des appels de queue?

Donc, si vous écrivez un style fonctionnel Ruby et que vous vous reposez sur le TCO d'une implémentation particulière, votre code peut être très inefficace dans un autre Ruby interprète. Je pense que cela c'est pourquoi Ruby n'est pas un langage fonctionnel (ni Python).

2
sastanin

Ruby n'est pas vraiment un langage multi-paradigme non plus, je pense. Le multi-paradigme a tendance à être utilisé par les personnes qui souhaitent étiqueter leur langue préférée comme quelque chose d'utile dans de nombreux domaines différents.

Je décrirais Ruby est un langage de script orienté objet. Oui, les fonctions sont des objets de première classe (en quelque sorte), mais cela n'en fait pas vraiment un langage fonctionnel. IMO, I pourrait ajouter.

2
JesperE

À strictement parler, il n'est pas logique de décrire un langage comme "fonctionnel"; la plupart des langages sont capables de programmation fonctionnelle. Même C++ l'est.

Le style fonctionnel est plus ou moins un sous-ensemble de fonctionnalités de langage impératives, pris en charge avec du sucre syntaxique et certaines optimisations du compilateur comme l'immutabilité et l'aplatissement de la récursivité de la queue

Ce dernier est sans doute une technicité mineure spécifique à la mise en œuvre et n'a rien à voir avec le langage réel. Le compilateur x64 C # 4.0 effectue une optimisation de récursivité de queue, tandis que celui de x86 ne le fait pas pour une raison stupide.

Le sucre syntaxique peut généralement être contourné dans une certaine mesure ou une autre, en particulier si le langage a un précompilateur programmable (c'est-à-dire #define de C).

Il serait peut-être un peu plus significatif de demander "le langage __ prend-il en charge la programmation impérative?", Et la réponse, par exemple avec LISP, est "non".

2
Rei Miyasaka

S'il vous plaît, jetez un œil au début du livre: "A-Great-Ruby-eBook" . Il aborde le sujet très spécifique que vous posez. Vous pouvez faire différents types de programmation dans Ruby. Si vous voulez programmer comme fonctionnellement, vous pouvez le faire. Si vous souhaitez programmer comme impérativement, vous pouvez le faire. Il s'agit d'une question de définition de la fonctionnalité de Ruby à la fin. Veuillez consulter la réponse de l'utilisateur camflan.