En Haskell, si j'écrisAccumulateurs à haskell
fac n = facRec n 1
where facRec 0 acc = acc
facRec n acc = facRec (n-1) (acc*n)
et compilez avec GHC, le résultat sera différent que si je
fac 0 = 1
fac n = n * fac (n-1)
Je pourrais facilement faire fac n = product [1..n]
et d'éviter la tout, mais je suis intéressé par la façon dont une tentative de récursion de la queue fonctionne dans un langage paresseux. Je comprends que je peux toujours avoir un débordement de pile parce que les thunks se construisent, mais est-ce que quelque chose se passe réellement différemment (en termes de programme compilé) quand j'utilise un accumulateur que lorsque je récapitule simplement la récursivité naïve? Y a-t-il un avantage à omettre la récursivité de la queue autre qu'une amélioration de la lisibilité? Est-ce que la réponse change du tout si j'utilise runhaskell
pour exécuter le calcul au lieu de le compiler en premier?
Quelle est votre définition de «est-ce que quelque chose se passe réellement différemment»? La réponse triviale est "oui", parce qu'ils sont différents - l'un est récursif et l'autre non. Mais je ne pense pas que c'est ce que vous demandez ..? – lijie
n'entendez-vous pas facRec n acc = facRec (n-1) (acc * n) ???? –
@lijie - Je m'intéresse principalement à savoir si GHC fait l'optimisation des appels de queue (avec ou sans accumulateur), mais je l'ai laissé général parce que je ne sais pas vraiment comment la récursivité de queue interagit avec les langages paresseux. choses basées sur mon utilisation d'une forme par rapport à une autre. Je ne sais pas ce que sont ces autres choses. – Inaimathi