l'inversion de liste en Lisp
Je suis en train d'inverser une liste en Lisp, mais j'obtiens l'erreur: "Erreur: Exception C0000005 [flags 0] à 20303FF3
{Offset 25 à l'intérieur de #}
eax 108 ebx 200925CA ecx 200 edx 2EFDD4D
esp 2EFDCC8 ebp 2EFDCE0 esi 628 edi 628 "
Mon code est comme suit:
(defun rev (l)
(cond
((null l) '())
(T (append (rev (cdr l)) (list (car l))))))
Quelqu'un peut me dire ce que je fais mal? Merci à l'avance!
Je l'utilise comme le "contraire" de la branche, après que toutes les conditions ont été vérifié..
La fonction de Common Lisp est correct. Qui lisp utilisez-vous? elisp?
LispWorks Personal Edition 6.1.1
Fonctionne très bien pour moi (LW PE 6.1.1 sur Mac). Comment faites-vous appel à
Seulement si le premier élément est un (sous-)de la liste.
La fonction de Common Lisp est correct. Qui lisp utilisez-vous? elisp?
LispWorks Personal Edition 6.1.1
Fonctionne très bien pour moi (LW PE 6.1.1 sur Mac). Comment faites-vous appel à
rev
?Seulement si le premier élément est un (sous-)de la liste.
OriginalL'auteur Nelly | 2015-12-22
Vous devez vous connecter pour publier un commentaire.
Votre code écrit est logiquement correct et produit le résultat que vous voulez:
Cela dit, il ya quelques problèmes avec elle en termes de performances. Le ajouter la fonction produit une copie de tous, mais son argument final. E. g., lorsque vous ne (append '(1 2) '(a b) '(3 4)), vous êtes en train de créer quatre nouveaux cons cellules, dont les voitures sont 1, 2, a et b. Le cdr de la dernière, c'est la liste existante (3 4). C'est parce que la mise en œuvre de ajouter est quelque chose comme ceci:
Ce n'est pas exactement Common Lisp est ajouter, puisque la Common Lisp est ajouter peut prendre plus de deux arguments. Il est assez proche de démontrer pourquoi tous, mais le dernier de la liste est copié, si. Maintenant, regardez ce que cela signifie en termes de mise en œuvre de rev:
Cela signifie que lorsque vous êtes à l'inversion d'une liste comme (1 2 3 4), c'est comme vous êtes:
Dans la ligne (2), vous êtes à la copie de la liste (4 3). En ligne, vous êtes la copie de la liste (4 3 2), qui comprend une copie de (4 3). Qui est, vous êtes de la copie d'une copie. C'est un joli gaspillage dans l'utilisation de la mémoire.
Une approche plus commune utilise un accumulateur variable et une fonction d'assistance. (Notez que j'utilise endp, reste, première, et liste* au lieu de null, cdr, voiture, et contre, car cela les rend plus clair le fait que nous travaillons avec des listes, pas arbitraire contre-arbres. Ils sont à peu près la même (mais il y a quelques différences).)
Avec cette fonction d'assistance, il est facile de définir rev:
Cela dit, plutôt que d'avoir un externe de la fonction d'assistance, il serait probablement plus courant d'utiliser étiquettes à définir une fonction d'assistance:
Ou, depuis Common Lisp n'est pas garanti pour optimiser la queue des appels, un ne boucle est agréable et propre, ici aussi:
J'ai encore une question.. si il y a des sous-listes dans la liste initiale? J'ai essayé de modifier un peu le code, à l'aide de "mapcar" en fonction dans "rev", mais j'obtiens le résultat "NUL" ... pouvez-vous me donner une suggestion?
Je ne suis pas du tout sûr de ce que vous entendez, et ne peut certainement pas à deviner quel est le problème que vous avez couru dans juste par "je obtenir le résultat de NÉANT". Vous n'avez pas besoin de modification pour les listes qui ont des listes d'éléments. Lorsque vous inversez ((1 2) (3 4)) vous obtenez ((3 4) (1 2)), une nouvelle liste avec les mêmes éléments, mais dans l'ordre inverse.
J'ai reçu votre point, et vous avez raison. Mais, je veux inverse également les éléments de sous-listes. Donc, c'est pourquoi j'ai écrit quelque chose comme: "( mapcar #'rev-helper liste '()) " dans "rev", et par exemple, l'appel " (rev '(1 2 '(3 4) 5 '(6 7))) "donne moi le résultat "NUL" ..
Je suis sur mobile à l'instant, donc je ne peux pas fournir une réponse complète. Tout d'abord, vous ne voudrez pas mettre plus de guillemets à l'intérieur des listes. C'est, ne '(1 2 (3 4)) pas '(1 2 '(3 4)) [je peux fournir un lien vers une autre question à ce sujet]. Deuxièmement, il y a une autre question à propos de l'inversion de façon récursive qui n'est probablement ce que vous voulez. Troisièmement, dans votre tentative, à l'aide de votre mapcar de manière incorrecte. Mapcar appelle les arguments de la fonction de chaque liste. E. g., (mapcar '+ (1 2) (3 4)) retourne (4 6), parce qu'il appelle + avec 1 et 3, puis 2 et 4. Si vous n' (mapcar #'rev-helper liste '()), la deuxième
OriginalL'auteur Joshua Taylor
Dans la norme ANSI Common Lisp, vous pouvez inverser une liste à l'aide de la
reverse
fonction (non destructif: alloue une nouvelle liste), ounreverse
(réorganise les blocs de construction ou de données de la liste existante pour produire de l'inversion).Ne pas utiliser
nreverse
sur les cours de la liste des littéraux; c'est un comportement indéfini, et peut se comporter de manière surprenante, puisqu'il est de facto self-modifying code.OriginalL'auteur Kaz
Si vous pouvez utiliser la norme CL des fonctions de la bibliothèque comme
append
, vous devez utiliserinverse
(comme Kaz a suggéré).Sinon, si c'est un exercice (h/l ou pas), vous pouvez essayer ceci:
PS. Votre erreur est incompréhensible, veuillez contacter votre fournisseur.
OriginalL'auteur sds
Vous avez probablement courir hors de la pile de l'espace; c'est la conséquence de l'appel d'une fonction récursive,
rev
, à l'extérieur de la queue de la position. L'approche de la conversion à une queue-fonction récursive implique l'introduction d'un accumulateur, la variableresult
le suivant:Vous
rev
fonction devient alors:Exemples:
consp
est le type de prédicat pour un "contre cell". Chaque liste est une séquence de cons cellules se terminant dans unnil
. Si vous essayez(cons 1 (cons 2 nil))
vous obtiendrez une liste de(1 2)
. Dans monreving
code ci-dessus, silist
est uncons
puis poussez lecar
surresult
et une boucle sur le reste de la liste (viacdr
).OriginalL'auteur GoZoner