La réponse à votre question directe est qu'il n'y a pas de surcharge introduite dans un appel de fonction simplement parce que cette fonction a plusieurs arités. Dans Clojure, tous les appels de fonction sont compilés dans un appel de méthode. La méthode exacte invoquée dépend du nombre d'arguments - en ce qui concerne la JVM, chaque arité est compilée comme une méthode différente. La détermination de la méthode à appeler est effectuée au moment de la compilation, donc il n'y a pas de surcharge au moment de l'exécution. Ceci étant dit, il y a une surcharge pour faire des appels de fonction imbriqués. Plus précisément, chaque appel augmente la pile d'appels d'une quantité constante jusqu'à ce que cet appel retourne. Cependant, ces frais généraux sont minimes et peu susceptibles d'avoir un impact mesurable sur la performance dans ce cas.
@ToniVanhala je l'ai fait avec laisser d'abord, mais un ami a dit que let est mauvais et non fonctionnel (il est un développeur de Erlang), je suis nouveau dans Langs fonctionnels ... autre chose qu'il dit est que c'est étrange que clojure est pas empilable
Cela semble être la vraie question. Donc ça vaut la peine d'aborder ça.
let
est simplement une expression qui nous permet de lier des valeurs à des variables. Ces liaisons sont immuables. En outre, il est bien connu que let
peut être implémenté comme une macro-abstraction sur lambda (ou, dans le vocabulaire de Clojure, fn
). Donc, il n'y a certainement rien à propos de let
qui le rend "pas fonctionnel".
Il n'y a rien de "bizarre" ou de déroutant que Clojure ne soit pas sans pile. Clojure est un langage JVM et une pile d'appels est profondément intégrée dans le modèle de calcul abstrait de la JVM. Bien qu'il existe des moyens de contourner ce problème (par exemple, le style de continuation-passing), ces méthodes nécessitent soit l'abandon de l'interopérabilité JVM profonde, soit le paiement d'une pénalité de performance. Clojure est avant tout un langage pragmatique, et c'est une concession pragmatique. En outre, Clojure (être un Lisp) est vraiment un cadre de langage avec lequel vous forgez la langue que vous voulez. Votre langue peut faire des compromis différents. Par exemple, votre langue peut être "stackless". Ou il pourrait avoir first-class continuations (avertissement: je suis l'auteur de pulley.cps
). Ou il peut avoir un completely different paradigm (c'est-à-dire, logique vs fonctionnel). Mais cela peut aussi être très simple. Avec Clojure, vous pouvez choisir ce que vous payez. Ironiquement, votre ami a raison de dire que le code n'est pas fonctionnel. Cependant, ce n'est pas à cause du let
. Plutôt, à peu près tout sauf le let
n'est pas fonctionnel.Par exemple, (save company options)
est clairement une opération à effet secondaire. Cependant, cela ne signifie pas nécessairement que votre code est mauvais - même le programme fonctionnel le plus pur doit, à un moment donné, interagir avec le monde réel s'il veut avoir une valeur pratique.
Y a-t-il une raison pour laquelle vous envisagez la première option avec multi-arité? A moins que la méthode ne soit appelée ailleurs avec les deux signatures, la seconde (avec let binding) est certainement moins encombrée. Je crois que vous économisez également un appel dans la pile, ce qui semble être un saut inutile dans le multi-arité. –
@ToniVanhala Je l'ai fait avec laissez d'abord, mais un ami a dit que let est mauvais et pas fonctionnel (il est un développeur erlang), je suis nouveau dans les langes fonctionnels ... l'autre chose qu'il a dit est que c'est clojure n'est pas empilée –
[L'expression "let" peut être considérée comme une abstraction lambda appliquée à une valeur] (https://en.wikipedia.org/wiki/Let_expression), donc elle correspond bien à la programmation fonctionnelle. –