11
votes

Fonctions anonymes récursives dans SML

est-il possible d'écrire des fonctions anonymes récursives dans SML? Je sais que je pouvais simplement utiliser la syntaxe code> dun code>, mais je suis curieux.

J'ai écrit, comme exemple de ce que je veux: p>

val fact =
    fn n => case n of
                 0 => 1
               | x => x * fact (n - 1)


2 commentaires

Je ne suis pas un expert sur ML, mais vous recherchez probablement quelque chose qui implique une combinaison de points fixe comme le combinateur Y, qui est la manière typique que vous pouvez créer une fonction récursive à partir de fonctions anonymes.


@TemplateTypeDEF Vous êtes correct tant que vous ne voulez que travailler avec des fonctions anonymes (gardant à l'esprit que la question initiale n'utilise pas de fonctions anonymes), mais ce n'est pas une jolie façon de le faire. Voir la dernière partie de ma réponse pour un exemple :)


4 Réponses :


8
votes

Tout ce que vous avez à faire est de mettre rec après val , comme dans xxx

wikipedia décrit cela près du sommet de la première section.


2 commentaires

Je t'ai eu. J'ai pensé que Wikipedia n'avait pas cette information, alors j'ai regardé partout, mais là-bas. Merci.


Merci beaucoup! :) Vous êtes un véritable économiseur de vie! :)



15
votes

La fonction anonyme n'est plus vraiment anonyme lorsque vous le liez à un variable. Et puisque VAL REC code> est juste la forme dérivée de amusement code> sans différence autre que l'apparence, vous pouvez aussi bien l'avoir écrit en utilisant La syntaxe amusante code>. Vous pouvez également faire correspondre des modèles dans fn code> expressions aussi comme dans cas code>, comme les cas sont dérivés de fn code>.

donc dans toute sa simplicité, vous auriez pu écrire votre fonction comme p> xxx Pré>

mais c'est exactement le même que celui ci-dessous plus lisible (dans mon adpinion) p> xxx pré>

aussi loin que je pense, il n'y a qu'une seule raison d'utiliser écrire votre code en utilisant le long VAL REC code>, et c'est parce que vous pouvez faciliter l'annotation de votre code avec Commentaires et types forcés. Pour des exemples si vous avez déjà vu du code Haskell avant et comme la façon dont ils tapent annotant leurs fonctions, vous pouvez l'écrire quelque chose comme ceci p> xxx pré>

comme TemplateTypedef mentionné, il est possible de le faire à l'aide d'un point fixe Combinateur. Un tel combinateur peut ressembler à p> xxx pré>

et vous pouvez ensuite calculer fait 5 code> avec le code ci-dessous, qui utilise anonyme fonctionne pour exprimer la fonction de la faculté puis lie le résultat de la calcul sur res code>. p> xxx pré>

Le code de point fixe et l'exemple de calcul sont la courtoisie de Morten Brã¸ns-Pedersen. P>


Réponse mise à jour à la réponse de George Kangas: H3>

dans les langues que je connais, une fonction récursive sera toujours liée à un Nom. La manière commode et conventionnelle est fournie par des mots-clés comme "Définir" ou "let", ou "Letrec", ... p> BlockQuote>

true true par définition. Si la fonction (récursif ou non) n'était pas liée à un nom, ce serait anonyme. P>

La voie non conventionnelle, plus anonyme, est de la liaison Lambda. P> BlockQuote>

Je ne vois pas de quoi il est non conventionnel sur les fonctions anonymes, ils sont utilisés tout le temps dans SML, en infustant dans n'importe quel langage fonctionnel. Il commence même à se présenter dans de plus en plus de langues impératives. P>

La réponse de Jesper Reenberg montre la liaison Lambda; le "anonyme" la fonction est liée aux noms "F" et "fait" de Lambdas (appelé "fn" dans SML). P> blockQuote>

La fonction anonyme est en fait anonyme (pas "anonyme" - pas de citations), et oui bien sûr, il sera lié dans la portée forte> de ce qui fonctionne jamais sur comme un argument. Dans tous les autres cas, la langue serait totalement inutile. La même chose est exacte lors de l'appelant carte (fn x => x) [.....] code>, dans ce cas, la fonction d'identité anonyme est toujours anonyme. P>

La définition "normale" d'une fonction anonyme (au moins selon wikipedia ), en disant qu'il ne doit pas être tenu de Un identifiant, est un peu faible et devrait inclure la déclaration implicite "dans l'environnement actuel". P>

Ceci est en fait vrai pour mon exemple, comme on le voit en l'exécutant à MLTON avec la base argument sur un fichier contenant uniquement amusant y ... code> et le val = .. code> p> xxx pré>

de ceci est vu qu'aucune des fonctions anonymes n'est liée dans l'environnement. P>

Une alternative "lambdanonymous" plus courte, qui nécessite OCAML lancé par "OCAML -Rectypes": P>

(fun f n -> f f n) 
(fun f n -> if n = 0 then 1 else n * (f f (n - 1))
7;; Which produces 7! = 5040.


2 commentaires

"[...] Etant donné que Val Rec est juste la forme dérivée du plaisir [...]": n'est-ce pas le contraire?


Non, bien peut-être que nous entendons la même chose, mais regardez-le de deux angles différents. VAL REC fait partie de la langue principale et le mot-clé est le formulaire dérivé. Je n'ai pas ma définition à portée de main, mais voir la section 3.4 de [ homepages.inf.ed.ac.uk/stg/notes/notes.pdf ] (c'était le meilleur que je puisse trouver sur Google).



-1
votes

Dans les langues que je connais, une fonction récursive sera toujours liée à un nom. La manière commode et conventionnelle est fournie par des mots-clés tels que "Définir" ou "let", ou "LETRec", ...

Le non conventionnel, plus anonyme regarder em>, way est par la liaison Lambda. La réponse de Jesper Reenberg montre la liaison Lambda; La fonction "anonyme" est liée aux noms "F" et "FAIT" de Lambdas (appelé "Fn" dans SML). P>

Une alternative "lambdanonyme" plus courte, qui nécessite OCAML lancé par "OCAML - RecTypes ": P>

(fun f n -> f f n)
(fun f n -> if n = 0 then 1 else n * (f f (n - 1))
7;;


1 commentaires

Avez-vous même lu le code? Répondre à un exemple OCAML n'apporte pas de valeur à la question initiale, en particulier lors de l'utilisation de types récursifs que SML n'a pas. Dans tout ce cas, je ne vois pas le point de votre poste autre que d'indiquer certains de savoir déjà des faits. Voir mon poste mis à jour.



2
votes
fix f => e   
  := let rec f = e in f end

let rec f = e ... in ... end 
  := let f = fix f => e ... in ... end 

0 commentaires