0
votes

Fonction récursive scala qui renvoie une autre fonction

Je cherchais des exemples de technique de curry à Scala et je ne comprenais pas comment une fonction peut renvoyer une autre fonction lorsqu'une fonction est récursive.

Par exemple, je comprends ce code P>

def repeater(myFunc: Int => Int, n:Int): Int => Int = {
   if(n<=0) (x:Int) => x
   else (x: Int) => repeater(myFunc, n-1)(myFunc(x))
}


0 commentaires

3 Réponses :


2
votes

Déplaions la réursion étape par étape.

répéteur (addone, 2) retourne nouvelle fonction anonyme xxx

répéteur (addone, 1) renvoie une nouvelle fonction anonyme xxx

répéteur (addone, 0) retourne nouvelle fonction anonyme xxx

par conséquent répéteur (addone, 1) retourne une fonction anonyme qui ressemble à xxx

et < Code> répéteur (addone, 2) renvoie une fonction anonyme qui ressemble à xxx


2 commentaires

Merci pour votre explication claire et brève. Penser avec Apply () La méthode est très utile et m'a fait comprendre plus facilement.


Bien sûr :) Mais je dois dire que trois de votre réponse sont bien expliquées et claires pour moi.



2
votes

Pour le rendre plus compréhensible, je vais simplifier et descendre une partie de votre fonction.

Soit d'abord supprimer MyFunc PARAMETER et le remplacer par Addone Fonction réduisant directement la complexité Garder la principale question dans la mise au point: xxx

désinversoc fonctionne le code d'instanciation littéral xxx

alors vous pouvez donc voir que vous pouvez voir que Lorsque vous appelez reporter (2) il produit une nouvelle fonction # 2 sans l'évaluer. Donc, au résultat, vous aurez quelque chose comme ceci: xxx

ou le sucre le sucre xxx

alors vous avez donc maintenant que vous avez maintenant val contenant la fonction littéral que vous pouvez appeler comme ceci répéteurfirsttraittration (...)


2 commentaires

Merci, Lambda Expression comme (x: int) => x + 1 et crée fonction (instance de classe réellement) avec fonction1 est totalement identique à droite? (Comme dans Java et des interfaces fonctionnelles.) Autant que je sache, les fonctions Scala et Java sont presque identiques dans la création.


Oui. (x: int) => x + 1 est juste un sucre de syntaxe pour créer une instance de classe. Autant que je sache, Lambdas dans Java fonctionne de la même manière.



2
votes

Tout d'abord, clarifions-nous si vous avez exécuté répéteur (addone, 3) code>, vous ne récupérerez qu'une fonction. Vous auriez besoin d'exécuter répéteur (addone, 3) (quelque purée) code> pour obtenir votre valeur entière et le résultat de votre calcul. Tout ce que la récursion fait ici consiste à construire une fonction. répéteur (addone, 3) code> renvoie une fonction qui prend un entier et retourne un entier. Prenez l'exemple de répéteur (addone, 3) code>, si nous écrivons le résultat de la récursion complète, c'est ce que nous obtenons xxx pré>

il pourrait ressembler un peu déroutant mais permet de le casser. p>

permet de se concentrer sur la partie la plus interne - {x => x} (myfunc (x)) code>. Cela peut être séparé en deux parties, une fonction et une entrée à la fonction. La fonction est {x => x} code> et l'entrée de cette fonction est (myfunc (x)) code>. Dans ce cas, tout ce que la fonction est renvoyée à l'utilisateur. Ainsi, si nous écrivons {x => x} (1) code> nous obtiendrons 1 code>. Nous pouvons donc remplacer l'ensemble du {x => x} (myfunc (x)) code> avec juste myfunc (x) code>. Ce qui nous reste, c'est p> xxx pré>

permet de regarder le {x => myfunc (x)} (myfunc (x)) code> terme. Ici, la partie de fonction est {x => myfunc (x)} code> et l'entrée de cette partie de fonction est donnée par (myfunc (x)) code>. La partie de fonction prend dans un entier x code> et applique myfunc code> à cet entiteur. C'est essentiellement la même chose que l'application myfunc code> directement sur cet entier. Dans ce cas, l'entier que nous l'appliquons est l'entrée myfunc (x) code> afin que nous puissions réécrire {x => myfunc (x)} (myfunc (x)) code > comme myfunc (myfunc (x)) code>. Maintenant, nous avons p> xxx pré>

Nous pouvons appliquer la même logique utilisée à l'étape précédente pour casser le {x => myfunc (myfunc (x))} (myfunc (x))) code> terme. Nous obtiendrions myfunc (myfunc (myfunc (x))) code>. Si vous continuez avec cette logique, vous verrez que répéteur code> va continuer à composer myfunc code>. Pour chaque n code>, il ajoutera une couche supplémentaire de myfunc code>. Le résultat de cela ressemblerait à ceci si n = 3 code> p> xxx pré>

donc pour répéteur (addone, 3) code>, nous obtiendions p> xxx pré>

et répéteur (addone, 5) code> est p> xxx pré>

tout ça Répéteur Code> Cela construit-il simplement cette fonction et le renvoie à l'utilisateur. Vous pouvez prendre cette fonction de retour de répéteur code> et mettre dans un val code> appelé f code> p> xxx pré>

f code> prend une entrée entière et renvoie qu'Eteger Plus 3. Nous pouvons alors obtenir le résultat réel que nous voulons utiliser ce P>

 val someIntegerPlus3: Int = f(someInteger)


0 commentaires