Ce qui est un Y-combinator?
Un Y combinator est une science de l'ordinateur le concept de la “fonctionnelle” côté des choses. La plupart des programmeurs ne savent pas beaucoup au sujet de combinators, si ils ont même jamais entendu parler.
- Ce qui est un Y-combinator?
- Comment combinators travail?
- À quoi servent-elles?
- Sont-ils utiles dans les langages procéduraux?
- Peu d'astuce, si vous en apprendre davantage sur les langages fonctionnels comme je le fais, mieux vaut laisser combinators jusqu'à ce que vous obtenez à l'aise avec elle, sinon, c'est une route à la folie...
- Arrivés à sourire à la gravatar de l'éditeur de cette question 🙂 lien sur Mads Torgensen blog
- Voir aussi: Claire, intuitive, le calcul du point fixe combinator (Y combinator)?
- J'ai écrit un court résumé de partage de ma compréhension du Y Combinator: gist.github.com/houtianze/b274e4b975a28fe08aee681699c3f7d0 je l'ai expliqué (à ma connaissance) comment le "Y Combinator fait fonction récursive"
- Comment cette question est "trop large"?
Vous devez vous connecter pour publier un commentaire.
Si vous êtes prêt pour une lecture longue, Mike Vanier a un grand explication. Longue histoire courte, il vous permet de mettre en œuvre la récursivité dans une langue qui n'est pas nécessairement en charge en mode natif.
Un Y combinator est un "fonctionnelle" (une fonction qui fonctionne sur d'autres fonctions) qui permet la récursivité, lorsque vous ne pouvez pas se référer à la fonction à partir de l'intérieur de lui-même. Dans la théorie des sciences, il généralise la récursivité, l'abstraction de sa mise en œuvre, et ce qui le sépare du travail réel de la fonction en question. L'avantage de ne pas avoir besoin d'un moment de la compilation du nom de la fonction récursive est une sorte de bonus. =)
C'est applicable dans les langues lambda fonctions. Le expression-en fonction de la nature des lambdas signifie généralement qu'ils ne peuvent pas se référer à eux-mêmes par leur nom. Et de travail autour de ce en déclarant la variable, qui est venu à elle, puis à attribuer le lambda-il, pour compléter l'auto-référence de la boucle, est fragile. Le lambda variable peut être copié, et la variable d'origine attribué à nouveau, ce qui rompt l'auto-référence.
Y combinators sont lourdes à mettre en œuvre, et souvent à utiliser, dans statique-tapé langues (les langages procéduraux est souvent le cas), parce que d'habitude de taper des restrictions exigent le nombre d'arguments de la fonction en question à être connu au moment de la compilation. Cela signifie qu'un y combinator doit être écrit pour tout argument compter que l'on doit utiliser.
Ci-dessous est un exemple de la façon dont l'utilisation et le fonctionnement d'un Y-Combinator, en C#.
À l'aide d'un Y-combinator implique un "inhabituel" la construction d'une fonction récursive. D'abord, vous devez écrire votre fonction comme un morceau de code qui appelle une pré-existante de la fonction, plutôt que de lui-même:
Alors vous transformer en une fonction qui prend une fonction à appeler, et retourne une fonction qui le fait. Cela s'appelle fonctionnel, car il faut une fonction, et effectue une opération avec elle que les résultats dans une autre fonction.
Maintenant, vous avez une fonction qui prend une fonction, et retourne une fonction qui donne l'impression d'être une factorielle, mais au lieu d'appeler lui-même, il appelle l'argument passé à la fonction externe. Comment voulez-vous faire de cette factoriel? Passer à la fonction interne à lui-même. Le Y Combinator fait que, en étant une fonction avec un nom permanent, qui peut introduire la récursivité.
Plutôt que la factorielle d'appel lui-même, ce qui se passe, c'est que la factorielle appelle la factorielle générateur (retourné par l'appel récursif à Y Combinator). Et en fonction de la valeur actuelle de t la fonction renvoyée à partir du générateur d'appeler le générateur encore, à t - 1, ou juste de retour de 1, la résiliation de la récursivité.
C'est compliqué et cryptique, mais tout s'équilibrera au moment de l'exécution, et la clé de son travail est "l'exécution différée", et la rupture de la récursivité à durée de deux fonctions. L'intérieur F est passé comme argument, d'être appelé dans la prochaine itération, seulement si nécessaire.
fix :: (a -> a) -> a
, et laa
à son tour, peut-être autant d'arguments que vous le souhaitez. Cela signifie que le typage statique n'a pas vraiment faire de cet encombrant.J'ai soulevé ce de http://www.mail-archive.com/[email protected]/msg02716.html qui est une explication que j'ai écrit il y a plusieurs années.
Je vais utiliser JavaScript dans cet exemple, mais de nombreuses autres langues de travail.
Notre objectif est d'être capable d'écrire une fonction récursive de 1
variable en utilisant uniquement les fonctions de 1 variables et pas de
d'affectations, de définir les choses par leur nom, etc. (Pourquoi c'est notre
but est une autre question, nous allons juste prendre ce que l'
le défi que nous nous sommes donnés). Semble impossible, hein? Comme
un exemple, nous allons mettre en œuvre factorielle.
Bien l'étape 1 consiste à dire que l'on peut faire facilement si nous
triché un peu. Utilisation des fonctions de 2 variables et
affectation du moins pouvons-nous éviter d'avoir à utiliser
cession pour configurer la récursivité.
Maintenant, nous allons voir si nous pouvons tricher moins. Eh bien tout d'abord que nous utilisons
d'affectation, mais nous n'avons pas besoin de. Il nous suffit d'écrire X et
Y en ligne.
Mais nous sommes à l'aide de fonctions de 2 variables pour obtenir une fonction de 1
variable. Pouvons-nous résoudre ce problème? Eh bien c'est un gars intelligent par le nom de
Haskell Curry a une astuce, si vous avez de bons d'ordre supérieur
fonctions vous avez seulement besoin de fonctions de 1 variable. L'
la preuve est que vous pouvez obtenir à partir de fonctions de 2 (ou plus dans le
cas général) des variables à 1 variable purement
mécanique de transformation du texte comme ceci:
où ... reste exactement la même. (Cette astuce est appelé
"nourrissage" d'après son inventeur. Le langage Haskell est également
nommé pour Haskell Curry. Fichier sous inutile de trivia.)
Maintenant, il suffit d'appliquer cette transformation partout et nous obtenons
notre version finale.
N'hésitez pas à essayer. alert() qui renvoient, de la lier à un bouton, que ce soit.
Ce code calcule factorielles, de manière récursive, sans l'aide de
d'affectation, de déclarations, ou des fonctions de 2 variables. (Mais
pour retrouver la trace de la façon dont il fonctionne est susceptible de vous faire tourner la tête.
Et de remettre, sans la dérivation, juste un peu reformaté
sera le résultat dans le code qui est sûr pour le déflecteur et les confondre.)
Vous pouvez remplacer les 4 lignes que de manière récursive définir factorielle avec
toute autre fonction récursive qui vous voulez.
function (n) { return builder(builder)(n);}
au lieu debuilder(builder)
?Je me demande si il n'y a aucune utilisation dans la tentative de construire ce à partir du sol. Voyons voir. Voici une base, la fonction factorielle récursive:
Nous allons refactoriser et de créer une nouvelle fonction appelée
fact
qui renvoie un anonyme factorielle-le calcul de la fonction au lieu d'effectuer le calcul en lui-même:C'est un peu bizarre, mais il n'y a rien de mal à cela. Nous en sommes seulement à la génération d'une nouvelle fonction factorielle à chaque étape.
La récursivité, à ce stade, est encore assez explicite. Le
fact
fonction doit être conscient de son propre nom. Nous allons paramétrer l'appel récursif:C'est très bien, mais
recurser
faut quand même savoir son nom propre. Nous allons paramétrer qu', trop:Maintenant, au lieu d'appeler
recurser(recurser)
directement, nous allons créer une fonction wrapper qui renvoie son résultat:On peut maintenant se débarrasser de la
recurser
nom de tout; c'est juste un argument de Y sont à l'intérieur de la fonction, qui peut être remplacée par la fonction elle-même:Externe, nom encore référencé est
fact
, mais il devrait être clair maintenant que c'est facilement paramétrable, aussi, la création de l'complet, générique, solution:recurser
. Pas la moindre idée de ce qu'il fait, ni pourquoi.recurser
fonction est la première étape vers cet objectif, car il nous donne une version récursive defact
que jamais des références de lui-même par son nom.function Y(recurse) { return recurse(recurse); } let factorial = Y(creator => value => { return value == 0 ? 1 : value * creator(creator)(value - 1); });
. Et c'est ainsi que je le digérer(pas sûr si c'est correct): Par pas explicitement référence à la fonction(non autorisé en tant que combinator), on peut utiliser deux partiellement appliquée/au curry fonctions(créateur de la fonction et de la fonction calculate), avec qui nous pouvons créer lambda/fonctions anonymes qui permettent d'atteindre récursive sans avoir besoin d'un nom pour la fonction calculate?La plupart des réponses ci-dessus décrivent ce que le Y combinator est, mais pas ce qu'il est pour.
Point fixe combinators sont utilisés pour montrer que lambda calcul est turing. C'est un résultat très important dans la théorie du calcul et fournit un fondement théorique à la programmation fonctionnelle.
L'étude de point fixe combinators m'a aussi permis de vraiment comprendre la programmation fonctionnelle. Je n'ai jamais trouvé d'aucune utilité dans la programmation si.
y combinator en JavaScript:
Modifier:
J'apprends beaucoup en regardant le code, mais celui-ci est un peu difficile à avaler sans quelques arrière-plan - désolé à ce sujet. Avec quelques connaissances générales présentées par d'autres réponses, vous pouvez commencer à chercher en dehors de ce qui se passe.
La fonction Y est le "y combinator". Maintenant, jetez un oeil à la
var factorial
ligne où Y est utilisé. Avis de passer une fonction qui a un paramètre (dans cet exemple,recurse
) qui est également utilisé plus tard dans l'intérieur de la fonction. Le nom du paramètre, fondamentalement, devient le nom de la fonction interne lui permettant de réaliser un appel récursif (car il utiliserecurse()
dans sa définition.) Le y combinator effectue la magie d'associer les anonymes intérieur de la fonction avec le paramètre nom de la fonction transmise à Y.Pour l'explication complète de la façon dont Y fait la magie, vérifié les article lié (pas par moi btw.)
arguments.callee
n'est pas autorisé en Mode Strict: developer.mozilla.org/en/JavaScript/...(function fact(n){ return n <= 1? 1 : n * fact(n-1); })(5)
Pour les programmeurs qui n'ont pas rencontré de la programmation fonctionnelle en profondeur, et ne se soucient pas de commencer maintenant, mais sont légèrement curieux:
Le Y combinator est une formule qui permet de mettre en œuvre la récursivité dans une situation où les fonctions ont pas de noms, mais peuvent être passés comme arguments utilisés comme valeurs de retour, et définis dans d'autres fonctions.
Il fonctionne par le passage de la fonction à lui-même comme un argument, de sorte qu'il peut s'appeler elle-même.
C'est une partie du lambda calcul, ce qui est vraiment maths mais est effectivement un langage de programmation, et est assez fondamental, à l'informatique et en particulier à la programmation fonctionnelle.
Au jour le jour à la pratique de la valeur de Y combinator est limité, car les langages de programmation ont tendance à vous laisser le nom des fonctions.
Dans le cas où vous avez besoin d'identifier une police de gamme, il ressemble à ceci:
Vous pouvez généralement place à cause de la répétition de l'
(λx.f (x x))
.La
λ
symboles sont la lettre grecque lambda, qui donne le lambda calcul de son nom, et il y a beaucoup de(λx.t)
style, parce que c'est ce que le lambda calcul ressemble.U x = x x
,Y = U . (. U)
(abusant de Haskell-comme la notation). OIE, avec une bonne combinators,Y = BU(CBU)
. Ainsi,Yf = U (f . U) = (f . U) (f . U) = f (U (f . U)) = f ((f . U) (f . U))
.D'autres réponses fournir assez concis réponse à cette question, sans que l'un fait important: Vous n'avez pas besoin de mettre en œuvre combinateur de point fixe dans la pratique de la langue dans ce tortueux chemin et de le faire ne sert aucun but pratique (à l'exception de "regardez, je sais de quoi Y combinator est"). Il est important concept théorique, mais de peu de valeur pratique.
Ici est un code JavaScript de la mise en œuvre du Y Combinator et de la fonction Factorielle (à partir de Douglas Crockford de l'article, disponible sur: http://javascript.crockford.com/little.html).
Un Y Combinator est un autre nom pour un flux condensateur.
J'ai écrit une sorte de "idiots guide" pour le Y Combinator dans les deux Clojure et un Schéma pour m'aider à venir à bout avec elle. Ils sont influencés par article dans "Le Petit Intrigant"
Dans Le Schéma:
https://gist.github.com/z5h/238891
ou Clojure:
https://gist.github.com/z5h/5102747
Les deux tutoriels sont code entrecoupés de commentaires et doit être coupé & pastable dans votre éditeur préféré.
Le y combinator met en œuvre anonyme de la récursivité. Ainsi, au lieu de
vous pouvez faire
bien sûr, le y combinator ne fonctionne qu'en appel par le nom de langues. Si vous souhaitez utiliser ce normal d'appel-par-valeur de la langue, alors vous aurez besoin de la liés à z combinator (y-combinator divergent/infinite loop).
Comme un débutant à combinators, j'ai trouvé Mike Vanier de l'article (merci Nicolas Mancuso) pour être vraiment utile. Je voudrais écrire un résumé, en plus de documenter ma compréhension, si elle pouvait être utile à d'autres, je serais très heureux.
De de Merde à Moins Merdique
À l'aide de factorielles comme un exemple, nous utilisons les
almost-factorial
fonction pour calculer le factoriel de nombrex
:Dans le pseudo-code ci-dessus,
almost-factorial
prend en fonctionf
et le nombrex
(almost-factorial
est au cari, de sorte qu'il peut être considéré comme prenant en fonctionf
renvoi d'un 1-arité de la fonction).Quand
almost-factorial
calcule la factorielle pourx
, il délègue le calcul de factorielle pourx - 1
à la fonctionf
et s'accumule à ce résultat avecx
(dans ce cas, il multiplie le résultat de (x - 1) x).Il peut être vu comme
almost-factorial
prend dans un de merde version de la fonction factorielle (qui ne peut calculer jusqu'au numérox - 1
) et renvoie un moins de merde version de factorielle (qui calcule jusqu'au numérox
). Comme dans ce formulaire:Si nous avons à plusieurs reprises passer le moins de merde version de factorielle de
almost-factorial
, nous finirons par obtenir notre fonction factoriellef
. Où il peut être considéré comme:Fix -
Le fait que
almost-factorial f = f
signifief
est le fix-point de la fonctionalmost-factorial
.C'était vraiment un moyen intéressant de voir les relations des fonctions ci-dessus, et c'était un moment aha pour moi. (veuillez lire Mike post sur fix-là, si vous ne l'avez pas)
Trois fonctions
De généraliser, nous avons un non-récursive fonction
fn
(comme la quasi-factorielle), nous avons son fix-point fonctionfr
(comme notre f), alors ceY
n'est lorsque vous donnezY
fn
,Y
retourne le fix-point de la fonction defn
.Donc en résumé (simplifié en supposant
fr
prend qu'un seul paramètre;x
dégénère àx - 1
,x - 2
... dans la récursivité):fn
:def fn fr x = ...accumulate x with result from (fr (- x 1))
, c'est le presque-utile fonction - bien que nous ne pouvons pas utiliserfn
directement surx
, il sera utile très bientôt. Cette non-récursivefn
utilise une fonctionfr
pour calculer son résultatfn fr = fr
,fr
est la correction du point defn
,fr
est le utile d'une fonction, on peut utiliserfr
surx
pour obtenir notre résultatY fn = fr
,Y
retourne le fix-point de fonction,Y
tourne notre presque-utile fonctionfn
en utilefr
Découlant
Y
(non inclus)Je vais sauter la dérivation de
Y
et aller à la compréhension deY
. Mike Vainer post a beaucoup de détails.La forme de
Y
Y
est définie comme (dans lambda calcul format):Si l'on remplace la variable
s
, à gauche de l'fonctions, nous obtenonsDonc en effet, le résultat de
(Y f)
est la correction du point def
.Pourquoi ne
(Y f)
travail?Selon la signature de
f
,(Y f)
peut être une fonction de toute arité, pour simplifier, supposons(Y f)
ne prend qu'un seul paramètre, à l'instar de notre fonction factorielle.depuis
fn fr = fr
, nous continuonsle récursive de calcul s'arrête lorsque l'intérieur de la plupart des
(fn fr 1)
est le cas de base etfn
ne pas utiliserfr
dans le calcul.Regardant
Y
de nouveau:Donc
Pour moi, la magie des pièces de cette configuration sont:
fn
etfr
interdepend les uns les autres:fr
'emballages"fn
à l'intérieur, chaque foisfr
est utilisée pour calculerx
, il engendre' ("soulève"?) unfn
et délègue le calcul pour quefn
(passage en lui-mêmefr
etx
); d'autre part,fn
dépendfr
et utilisefr
pour calculer une moindre problèmex-1
.fr
est utilisé pour définirfn
(quandfn
utilisefr
dans ses opérations), le réelfr
n'est pas encore défini.fn
qui définit le véritable logique d'entreprise. Basé surfn
,Y
créefr
- une fonction d'assistance dans un formulaire spécifique afin de faciliter le calcul pourfn
dans un récursive manière.Il m'a aidé à comprendre
Y
de cette façon, pour le moment, espérons que cela aide.BTW, j'ai aussi trouvé le livre Une Introduction à la Programmation Fonctionnelle Par le biais de Lambda Calcul très bon, je suis seulement en partie grâce à elle et le fait que je ne pouvais pas obtenir ma tête autour de
Y
dans le livre m'a amené à ce poste.Voici des réponses à la questions originales, compilée à partir de l'article (qui est VRAIMENT la peine de lire) mentionné dans le réponse par Nicolas Mancuso, ainsi que d'autres réponses:
Un Y combinator est un "fonctionnelle" (ou d'une fonction d'ordre supérieur — une fonction qui fonctionne sur d'autres fonctions) qui prend un seul argument, qui est une fonction n'est pas récursive, et renvoie une version de la fonction qui est récursive.
Un peu recursive =), mais plus en profondeur définition:
Un combinator — est juste une expression lambda sans variables libres.
Libre variable est une variable qui n'est pas une variable liée.
Lié variable — variable qui est contenue à l'intérieur du corps d'une expression lambda qui a le nom de la variable que l'un de ses arguments.
Une autre façon de penser à ce sujet est que combinator est une expression lambda, dans laquelle vous êtes en mesure de remplacer le nom d'un combinateur avec sa définition partout où il est présent et ont tout le travail (vous allez entrer dans une boucle infinie si combinator contiendrait référence à lui-même, à l'intérieur du corps de lambda).
Y combinator est un point fixe du combinator.
Point fixe d'une fonction est un élément de la fonction de domaine de ce qui est mappé à lui-même par la fonction.
C'est-à-dire,
c
est un point fixe de la fonctionf(x)
sif(c) = c
Cela signifie
f(f(...f(c)...)) = fn(c) = c
Exemples ci-dessous supposent forte + dynamique tapant:
Paresseux (normal-commande) Y-combinator:
Cette définition s'applique aux langues avec lazy (aussi: différé, appel par nécessité) d'évaluation — évaluation de la stratégie, ce qui retarde l'évaluation d'une expression jusqu'à ce que sa valeur est nécessaire.
Ce que cela signifie, c'est que, pour une fonction donnée
f
(qui est un non-récursive de la fonction), la fonction récursive peut être obtenue d'abord par le calculλx.f(x x)
, puis en appliquant cette expression lambda pour lui-même.Strict (applicative-commande) Y-combinator:
Cette définition s'applique aux langues avec la plus stricte (aussi: désireux, avide) d'évaluation — évaluation de la stratégie dans lequel une expression est évaluée dès qu'il est lié à une variable.
C'est même comme un paresseux dans sa nature, il a juste un supplément de
λ
wrappers pour retarder le lambda du corps de l'évaluation. J'ai demandé à une autre question, plus ou moins liés à ce sujet.Volempruntés réponse par Chris Ammerman: Y-combinator généralise la récursivité, l'abstraction de sa mise en œuvre, et ce qui le sépare du travail réel de la fonction en question.Même si, Y combinator a quelques applications pratiques, c'est surtout un concept théorique, la compréhension de qui permettra d'élargir votre vision globale et, probablement, une augmentation de votre analyse et des compétences de développeur.
Comme déclaré par Mike Vanier: il est possible de définir un Y combinator dans de nombreux langages statiquement typés, mais (au moins dans les exemples que j'ai vu), ces définitions exigent habituellement une certaine non-évidente type hackery, parce que le Y combinator lui-même ne dispose pas d'un simple de type statique. C'est au-delà de la portée de cet article, donc je n'en parle pas plus
Et comme mentionné par Chris Ammerman: la plupart des langages procéduraux a statique-typage.
Afin de répondre à un — pas vraiment.
Anonyme récursivité
Un point fixe du combinator est une fonction d'ordre supérieur
fix
que, par définition, satisfait de l'équivalencefix f
représente une solutionx
pour le point fixe de l'équationLa factorielle d'un nombre naturel peut être prouvé par
À l'aide de
fix
, arbitraire des preuves constructives sur le général/μ-fonctions récursives peuvent être calculées sans les nonymous l'auto-référentialité.où
tels que
Cette preuve formelle que
méthodiquement utilise le point fixe du combinator équivalence pour réécrit
Lambda calcul
La non typée lambda calcul formalisme consiste dans un contexte de grammaire
où
v
de chaînes de variables, en collaboration avec le bêta et eta réduction règlesBêta de réduction des succédanés de toutes gratuit les occurrences de la variable
x
dans l'abstraction (“fonction”) corpsB
par l'expression (“argument”)E
. Eta réduction en éliminant les doublons d'abstraction. Il est parfois omis dans le formalisme. Un irréductible expression, à laquelle aucune réduction de la règle s'applique, est en normal ou forme canonique.est un raccourci pour
(abstraction multiarity),
est un raccourci pour
(application à gauche-associativité),
et
sont alpha-équivalent.
L'Abstraction et de la demande sont les deux seuls “langues primitives” du lambda calcul, mais elles permettent de encodage arbitrairement complexes de données et d'opérations.
L'Église, les chiffres sont un codage des nombres naturels semblables aux Peano-axiomatique naturals.
Une preuve formelle que
à l'aide de la règle de réécriture de la bêta de réduction:
Combinators
En lambda calcul, combinators sont des abstractions qui ne contiennent pas de variables libres. Plus simplement:
I
, l'identité du combinatorisomorphe à l'identité de la fonction
Tels combinators sont les primitives opérateurs de combinator calculs comme les pistes de SKI du système.
Bêta de réduction n'est pas fortement normalisant; non pas réductible expressions, “redexes”, de converger vers une forme normale en vertu de la bêta de réduction. Un exemple simple est l'application divergente de l'omega
ω
combinatorà lui-même:
Réduction de gauche sous-expressions (“tête”) est une priorité. Applicative afin normalise les arguments avant de substitution, ordre normal ne le fait pas. Les deux stratégies sont analogues à ceux désireux d'évaluation, par exemple C, et de l'évaluation différée, par exemple, Haskell.
diverge sous désireux applicative ordre bêta réduction
depuis dans stricte sémantique
mais converge en vertu de paresseux normal d'ordre bêta réduction
Si une expression a une forme normale, normale ordre bêta réduction de la trouver.
Y
La propriété essentielle de la
Y
point fixe combinatorest donnée par
L'équivalence
est isomorphe à
Le type lambda calcul peut encoder arbitraire des preuves constructives sur le général/μ-fonctions récursives.
(Multiplication retard, confluence)
Pour Churchian non typée lambda calcul, il a été démontré pour un récursivement énumérable infinité de point fixe combinators outre
Y
.Normal d'ordre bêta réduction rend le rangement de type lambda calcul un de Turing-réécriture complète du système.
En Haskell, le point fixe du combinator peuvent être élégamment mis en œuvre
Haskell paresse normalise pour un fini avant que toutes les sous-expressions ont été évalués.
λ x . x
, comment êtes-vous aujourd'hui?Un combinateur de point fixe (ou point fixe de l'opérateur) est une fonction d'ordre supérieur qui calcule un point fixe d'autres fonctions. Cette opération est pertinent dans le langage de programmation théorie car elle permet la mise en œuvre de la récursivité dans la forme d'une règle de réécriture, sans le soutien explicite de la langue du moteur d'exécution. (src Wikipedia)
La ce-opérateur peut vous simplifier la vie:
Alors, vous évitez la fonction supplémentaire:
Enfin, vous appelez
fac(5)
.Je pense que la meilleure façon de répondre à cette est de choisir une langue, comme le JavaScript:
Maintenant réécrire afin qu'il n'utilise pas le nom de la fonction à l'intérieur de la fonction, mais encore l'appelle récursivement.
Le seul endroit où le nom de la fonction
factorial
doit être considéré est sur le site d'appel.Astuce: vous ne pouvez pas utiliser des noms de fonctions, mais vous pouvez utiliser des noms de paramètres.
Travailler sur le problème. Ne pas le regarder. Une fois que vous le résoudre, vous comprendrez ce problème le y combinator en résout.