Est-il rien de semblable à l'instruction de retour de C en Lisp?
Je veux mettre en œuvre une condition de base dans une fonction récursive écrit en Lisp, mais je ne suis pas capable de faire cela, car il n'y a pas de return dans Lisp.
Mon code Lisp est basé sur ce code C
if (n==0) return;
Comment puis-je mettre en œuvre cette en Lisp?
Lisp est souvent utilisé comme un langage de programmation fonctionnel. Cela signifie sorties à terme/stdout sont considérés comme des "effets secondaires" et un peu (sans donc une forte connotation négative) impur. Bien sûr, n'importe quelle fonction en Common Lisp permettra d'évaluer le bas pour que la valeur de ses finalmost forme.
Donc pour quelque chose comme abandonner tout cela si n est égal à 0 dans une fonction que nous appellerons #'foo vous auriez probablement utiliser un conditionnel dans la plupart des cas, ce serait probablement le #'cond fonction mais ici, c'est une simple mise en œuvre à l'aide de #'quand, souvent intégré dans une macro.
lisp n'est plus fonctionnel que le perl, à l'exception de la plus simple de le citer. certains problèmes ne peuvent être résolus dans un style fonctionnel sans la mettre dans une machine d'état qui effectivement fait la même chose que du code impératif sauf les transformations de l'environnement sont fait par copie à chaque opération. un de ces problèmes est la réduction partielle, où vous voulez réduire une liste d'étapes lors de la transformation de l'environnement, mais arrêter de réduire lorsqu'une certaine condition est remplie; "impératif" code efficacement les résumés de la complexité de ce, alors que les "pure fonctionnelle" du fait qu'il est impossible.
par exemple, une pure approche fonctionnelle des luttes avec l'expression
Donc pour quelque chose comme abandonner tout cela si n est égal à 0 dans une fonction que nous appellerons #'foo vous auriez probablement utiliser un conditionnel dans la plupart des cas, ce serait probablement le #'cond fonction mais ici, c'est une simple mise en œuvre à l'aide de #'quand, souvent intégré dans une macro.
(when (= n 0) (return-from foo nil))
Ci-dessus si formulaire, le nul peut être remplacé par une forme plus compliquée, mais si c'est nécessaire, vous aurez probablement envie de construire une mise en œuvre de (cond)
ou (case)
etcetera.lisp n'est plus fonctionnel que le perl, à l'exception de la plus simple de le citer. certains problèmes ne peuvent être résolus dans un style fonctionnel sans la mettre dans une machine d'état qui effectivement fait la même chose que du code impératif sauf les transformations de l'environnement sont fait par copie à chaque opération. un de ces problèmes est la réduction partielle, où vous voulez réduire une liste d'étapes lors de la transformation de l'environnement, mais arrêter de réduire lorsqu'une certaine condition est remplie; "impératif" code efficacement les résumés de la complexité de ce, alors que les "pure fonctionnelle" du fait qu'il est impossible.
par exemple, une pure approche fonctionnelle des luttes avec l'expression
find the index of the string "hi" in my array xs
, parce que réduire devez aller à travers l'ensemble du tableau, même après qu'il trouve, et le filtre d'aller à travers l'ensemble de la baie et de ne pas même savoir ce que la première est qu'il est destiné à être un non-ordonnée de l'opération. Donc, il n'y a aucun moyen d'exprimer ce problème correctement sans la mettre dans une machine d'état/stream/"monade", et une telle approche est isomorphe à l'impératif d'approche.
OriginalL'auteur Akash Babu | 2014-10-09
Vous devez vous connecter pour publier un commentaire.
Common Lisp a la forme spéciale DE RETOUR DE (et de sa relative De RETOUR) à faire ce que vous voulez.
Cela dit, je préfère utiliser COND lors de l'écriture de fonctions récursives.
cond
n'a pas les formes du corps, puis, si le formulaire de test renvoie non-nul, le résultat de l'essai formulaire est retourné. Cela signifie que vous pouvez écrire(cond ((null list) 0) ((+ (first list) ...)))
; il n'y a pas besoin de lat
dans ce cas.commentaire ne s'applique pas à la CL.) Dans le Schéma, c'est toujours mieux d'utiliser
else
au lieu d'utiliser l'expression en tant que forme de test, parce que leelse
expression est en queue de position, alors que le formulaire de test doit encore être testé pour truthiness.Merci. Je ne le savais pas.
Bon point sur le Régime de/CL différences; la question est de tagged lisp, de sorte qu'il n'est pas clair quelle est la cible Lisp est, mais cette réponse utilise
defun
, donc, j'avais supposé Common Lisp. Je peux voir pourquoi un stand-alone, le test non-queue de position si il y a des clauses suivantes, mais si c'est la dernière clause, ne serait pas un test stand-alone être dans la queue de position. E. g., dans(cond ... ((+ 2 3)))
si vous obtenez tout le chemin à(+ 2 3)
, alors que va être la valeur de retour. Il est juste comme la(and ... last)
et(or ... last)
cas, n'est-ce pas?réaliser, cependant, ce Régime a une liste précise des choses qui sont en queue de positions, de sorte que cela peut ne pas être couvert.)
OriginalL'auteur Mark Cox
Pour un Algol programmeur (ou l'un de ses nombreux dialectes, comme C, Java, perl, ...) chaque expression dans un LISP qui fonctionne comme un "return". Exemple:
En LISP cela peut être écrite comme:
Comme vous pouvez le remarquer LISP
if
est plus comme à l'opérateur ternaire( expression ? consequent : alternative )
d'un Cif
.MODIFIER
Maintenant que vous avez ajouté un exemple en utilisant
return
en C laquelle vous souhaitez traduire, je vois que vous n'êtes pas à l'aide dereturn
pour retourner une valeur, mais comme unegoto
pour quitter la fonction tôt. Depuis goto est toujours considéré comme nuisible juste à l'aide de CLreturn-from
n'est pas toujours la bonne réponse, même si ce serait certainement la meilleure traduction littérale.Dans toute LISP, vous devez fournir une valeur de retour, même si vous n'allez pas l'utiliser (pour les fonctions appelées par leurs effets secondaires). Si vous n'allez pas utiliser la valeur que vous pouvez simplement utiliser
nil
:Si vous avez besoin de plus d'une instruction (pour les effets secondaires que vous utilisez
let
,progn
ou échanger la totalité de la chose à uncond
:return-from
lorsqu'il est appelé, de manière algorithmique. 🙂J'aime la notion de elle encore être considérée comme néfaste et qu'il y a des exceptions. De cette façon, vous pensez à chaque fois que vous l'écrivez. C'est comme
call/cc
dans le Schéma, je n'ai presque jamais utiliser.Personnellement, j'aime bien structuré localisé gotos. YMMV, comme dire. 🙂 Tout récemment, j'ai codé des boucle en C avec deux points d'entrée, ce qui a parfois eu à effectuer à l'interne de l'initialisation (suite de la
concatMap ... span ...
paradigme, fondamentalement, le travail par morceaux, mais la production d'un plat de sortie). Jouer avec drapeaux semble tellement messier, pour moi.OriginalL'auteur Sylwester
Vous venez de faire l'
if
être pour le corps entier, et de mettrenil
plutôt quereturn
si vous voulez vraiment le retour à retour de "rien".Donc à ajouter tous les nombres de 0 à n:
Donc si
n==0
, le récursive de la fonction retourne 0. Sinon, il exécute le plus à ajoutern
àf(n-1)
et renvoie ce résultat. (Veuillez noter que ceci est pas l'idéal de l'algorithme, juste un exemple d'une fonction récursive).Rappelez-vous, Lisp renvoie la valeur de ce que expr dernière exécution en fonction de sa valeur. Si
n==0
, le ci-dessus renvoie 0. Sin > 0
, elle renvoie le résultat de la+
expr.Si vous avez besoin d'un multi-étape de test (par exemple, assurez-vous que vous n'êtes pas passé un nombre négatif),
cond
est la voie (comme mentionné précédemment). De toute façon, la valeur de la dernière chose exécutée est la valeur de la fonction.OriginalL'auteur eric.green