Ruby est-il un langage fonctionnel?

87

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

Esteban Araya
la source
4
Probablement parce que votre question est très courte, même si personnellement je n'ai aucun problème avec elle!
ljs
Il y a déjà de bonnes réponses, donc juste pour les compléter, une paire de contenus qui traitent de FP et Ruby: code.google.com/p/tokland/wiki/RubyFunctionalProgramming slideshare.net/tokland/functional-programming-with-ruby-9975242
tokland
1
Si quelqu'un est intéressé par ce sujet, regardez ceci et vous apprendrez comment ruby ​​peut être utilisé de manière fonctionnelle, quelles sont les racines de la programmation fonctionnelle, pourquoi ruby ​​n'est pas un langage fonctionnel même s'il est capable de programmer fonctionnel: youtube .com / watch? v = 5ZjwEPupybw
maddin2code

Réponses:

29

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 de savoir si le langage prend en charge des fonctions d'ordre supérieur ... ce que fait Ruby.

Cela dit, il est également facile de programmer en Ruby dans un style non fonctionnel. Un autre aspect clé du style fonctionnel est de ne pas avoir d'état et d'avoir de vraies fonctions mathématiques qui renvoient toujours la même valeur pour un ensemble donné d'entrées. Cela peut être fait dans Ruby, mais cela 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.

Mike Stone
la source
4
En utilisant ce critère, diriez-vous que Smalltalk est fonctionnel parce qu'il a des blocs?
OscarRyz
Bonne réponse, mais une nitpick - les fonctions d'ordre supérieur ne sont pas strictement nécessaires pour un style fonctionnel. Par exemple, vous pouvez obtenir un style fonctionnel en Java (qui n'a pas de fonctions de première classe / d'ordre supérieur) en définissant des objets fonction et en les composant pour obtenir le même effet qu'une fonction d'ordre supérieur.
mikera
2
Je veux juste dire que @peter a demandé Is ruby a functional language?et dans une réponse directe est un simple non. Ruby est un langage orienté objet avec quelques fonctionnalités.
Elias Perez
58

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 disposé à réaliser la thèse de la programmation fonctionnelle? La réponse est «très mal».

J'ai fait une présentation à ce sujet tout récemment. Voici les diapositives.

Tony Morris
la source
3
Les diapositives que vous avez données ne mentionnent pas pourquoi Ruby est «très peu disposé à réaliser la thèse de PF». Pourquoi C # est-il plus accessible que Java (OK, des fonctions anonymes plus faciles?)? Est-ce parce que vous pouvez avoir des variables globales dans Ruby?
kizzx2
7
Non, les diapositives n'entrent pas dans ce détail, car il s'agit d'un sujet assez vaste. Au risque d'une simplification excessive, par exemple, Ruby applique un modèle d'évaluation (appel par valeur) qui garantit la non-compositionnalité des programmes. Les implications de ceci peuvent facilement être sous-estimées. Ruby est également mariée à l'idée qu'un programme est une séquence d'effets. C'est-à-dire que Ruby fait tout son possible pour rendre difficile / intraitable l'utilisation de tout autre modèle de calcul. J'espère que ce bref commentaire vous aidera.
Tony Morris du
2
+1 pour souligner l'ambiguïté dans la classification des langues comme fonctionnelles. Enfer, j'ai écrit C fonctionnel!
Eli
1
Pourquoi C # est-il plus adapté que Ruby?
dan_l
1
En fait, une réponse de lien seulement car elle sous-traite la partie critique de l'explication (toute l'explication, en fait) vers un lien externe. Maintenant que le lien est mort, la réponse est devenue inutile.
ivan_pozdeev
34

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

L'une des principales caractéristiques d'un langage fonctionnel est qu'il évite l'état mutable. Les langages fonctionnels n'ont pas le concept de variable comme vous le feriez 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 écrites en utilisant une séquence d'instructions. Dans un langage fonctionnel, vous ne spécifiez pas de séquence d'exécution, même au niveau le plus bas.

Mike
la source
3
Je suis d'accord avec la plupart de votre déclaration, cependant, je ne suis pas d'accord sur le fait que "les langages fonctionnels n'ont pas le concept de variables comme vous le feriez en Java, etc." Dans haskell, vous pouvez utiliser des variables dans des fonctions pures, vous pouvez même affecter une fonction à une variable, la plus grande différence est qu'une fois qu'une variable est affectée, elle ne peut pas être modifiée par la suite.
HHC
6
HHC, par définition, une variable est une valeur qui peut changer . Ce dont vous parlez, ce sont des valeurs.
Scala Newb
En effet, les «variables non modifiables» de Haskell ne sont que des fonctions constantes sans paramètres (définitions).
raindev
16

Je soutiens 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 du code Java dans un style fonctionnel si je veux blesser mes collègues et moi-même quelques mois plus tard.

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 currying. 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 quand le code est plus facile à raisonner, les bogues deviennent moins profonds et flottent à la surface conceptuelle où ils peuvent être corrigés, ce qui à son tour donne moins de code bogué.

Ruby est essentiellement orienté objet, donc même s'il supporte raisonnablement un style fonctionnel, ce n'est pas en soi un langage fonctionnel.

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

Edit: Rétrospectivement et compte tenu des beaux commentaires que j'ai reçus jusqu'à présent sur cette réponse, je pense que la comparaison orientée objet par rapport à la fonction est celle des pommes et des oranges.

Le vrai différenciateur est celui d'être imparatif dans l'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 utilisée uniquement en cas de besoin. Dans un langage imparatif, l'exécution stricte est la valeur par défaut et bien que l'exécution paresseuse soit possible, elle est souvent compliquée à faire et peut avoir des résultats imprévisibles dans de nombreux cas extrêmes.

Maintenant, c'est mon opinion non scientifique.

Chris Vest
la source
Je pense que vous pouvez faire un bien meilleur cas pour appeler Ruby fonctionnel que Java .... non, Ruby n'est pas strictement fonctionnel, mais il est assez facile d'y utiliser un style fonctionnel ... et un collègue de style non fonctionnel peut changez-le facilement en non fonctionnel
Mike Stone
1
Oui, Mike, si vous voulez coder dans un style fonctionnel, Ruby est une énorme amélioration par rapport à Java. Je n'utilisais Java que pour exagérer et marteler le point d'origine.
Chris Vest
Donc, puisque D a des fonctions pures, vous appelleriez D un langage fonctionnel? digitalmars.com/d/2.0/function.html#pure-functions
Peter Burns
3
Beaucoup de gens considèrent les langages fonctionnels Lisp et Scheme, en grande partie en raison de l'utilisation omniprésente des fonctions anonymes. Et pourtant, ils manquent de fonctions pures garanties. Limiter le terme aux langages prenant en charge des fonctions pures semble beaucoup trop restrictif.
skymt
13

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

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 figer chaque variable manuellement.

Pas d'effets secondaires: fois passée une valeur donnée, une fonction doit toujours renvoyer 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 des fonctions d'ordre supérieur, le currying transforme une fonction qui prend plusieurs arguments en une fonction qui prend un argument. Cela va de pair avec l'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écursivité: boucle en appelant une fonction de l'intérieur d'elle-même. Lorsque vous n'avez pas accès aux données mutables, la récursivité est utilisée pour construire et enchaîner la construction des données. En effet, la boucle n'est pas un concept fonctionnel, car elle nécessite la transmission de variables pour stocker l'état de la boucle à un moment donné.

Évaluation paresseuse ou évaluation différée: retarder le traitement des valeurs jusqu'au moment où il est réellement nécessaire. Si, à titre d'exemple, vous avez un code qui a généré une liste de numéros de Fibonacci avec l'évaluation paresseuse activée, cela ne sera pas réellement traité et calculé tant que l'une des valeurs du résultat ne sera pas requise par une autre fonction, telle que put.

Proposition (juste une réflexion) Je serais bien d'avoir une sorte de définition pour avoir une modedirective pour déclarer des fichiers avec un paradigme fonctionnel, exemple

mode 'fonctionnel'

Elias Perez
la source
2
Je vous en prie. Je voudrais vous inviter à lire sur les langages fonctionnels. Lisp étant le grand-parent de toutes les langues fonctionnelles, ML (CAML) et Erlang / Elixir. Cela change vraiment votre perspective des choses. Je suis loin d'être un expert mais un étudiant constant en informatique aime lire et apprendre de nouvelles choses.
Elias Perez
Réponse bien organisée. J'aurais aimé une exploration supplémentaire de la façon dont le rubis soutient ces choses. Je crois que les fonctions d'ordre supérieur, le currying et la récursivité sont tous pris en charge / possibles dans ruby, veuillez me corriger si je me trompe.
Michael Dorst
9

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

skymt
la source
8
fournir des preuves
Mirzhan Irkegulov
4

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

exemple:

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

Lisez ici ou ici

camflan
la source
Je n'ai jamais vraiment compris comment "tout est objet" rend Ruby plus OO. Je conviens que Ruby est principalement OO, mais "tout est un objet" signifie en réalité qu'il n'y a pas de types "primitifs", ce qui a très peu d'incidence sur la capacité du développeur à écrire des programmes en style OO, étant donné que l'existence de primitifs types signifie généralement qu'il existe quatre ou cinq types qui n'ont aucune méthode.
Michael Dorst
4

Cela dépend de votre définition d'un «langage fonctionnel». Personnellement, je pense que le terme est lui-même 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 de langage 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 de Common Lisp? Mis à part le problème d'espace de noms multiple / unique et l'élimination garantie des appels de queue (que certaines implémentations CL prennent également en charge, en fonction des paramètres du compilateur), il n'y a pas grand-chose qui rend Scheme en tant que langage plus adapté à la programmation fonctionnelle que Common Lisp, et encore, la plupart des lispers n'appelleraient pas CL un langage fonctionnel. Pourquoi? Parce que la culture qui l'entoure dépend fortement des fonctionnalités 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 que votre bloc de code C habituel, 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 par oui / non. Le fait d'appeler un langage fonctionnel ou non dépend fortement de votre point de vue.

Matthias Benkard
la source
En quoi Haskell n'est-il pas un langage purement fonctionnel? Ou que diriez-vous de Miranda (un langage de programmation fonctionnel moins connu)? courses.cs.washington.edu/courses/cse505/99au/functional/… "Haskell est un langage purement fonctionnel standard,"
barlop
2

Ruby n'est pas non plus vraiment un langage multi-paradigme, 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, pourrais-je ajouter.

JesperE
la source
4
Le type de langage est défini par les styles de programmation qu'il prend en charge; cela, à son tour, est décidé par les fonctionnalités dont il dispose. Fonctions de première classe et anonymes = programmation fonctionnelle minimale. Ruby prend en charge la programmation OO mais ne l'exige pas: vous n'avez jamais besoin de définir une classe. Par conséquent, multi-paradigme.
skymt
2

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 d' optimisation des appels de queue (TCO).

Les langages de programmation fonctionnels sont capables d'optimiser la récursivité de la queue et peuvent exécuter un tel code dans un espace constant. Certaines implémentations de Ruby optimisent la récursivité de la queue, d'autres non, mais en général, les implémentations de Ruby ne sont pas obligées de faire le TCO. Consultez Ruby effectue-t - il une optimisation des appels de queue?

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

sastanin
la source
Le TCO est intéressant, car il modifie essentiellement le comportement du programme. Dans certains cas, ce n'est pas visible pour le programme, mais dans d'autres cas, c'est, par exemple, des backtraces d'exception. Par conséquent, ce n'est pas toujours une optimisation appropriée.
ioquatix
2

À proprement parler, cela n'a pas de sens 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 le sucre syntaxique et certaines optimisations du compilateur comme l'immuabilité et l'aplatissement de la récursivité de la queue,

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

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

Il serait peut-être un peu plus significatif de se demander "est-ce que le langage __ supporte la programmation impérative?", Et la réponse, par exemple avec Lisp, est "non".

Rei Miyasaka
la source
1

S'il vous plaît, jetez un œil au début du livre: "A-Great-Ruby-eBook" . Il traite du 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 voulez programmer comme impérativement, vous pouvez le faire. C'est une question de définition à quel point Ruby est fonctionnel à la fin. Veuillez consulter la réponse de l'utilisateur camflan.

Léo Léopold Hertz 준영
la source