Dans le sens le plus poli, votre code est un peu hors tension. Tu apprends Lisp cette semaine, n'est-ce pas? C'est bon! C'est un langage amusant et peut vraiment faire des choses géniales. Je vais donc passer en revue la création de la routine et vous emmener le long de la visite.
Votre cas de base est -
(defun negate (n)
(if (> n 0) (- 0 n)))
(map #'negate '(1 2 3 4))
marche l'arbre est plus complexe, mais nous allons marcher à travers les idées. Essentiellement, vous avez trois cas pour répondre: l'élément courant est-il nul, une liste ou un atome?
(if (not (car seq))
(if (listp (car seq))
;;Recurse
;;Otherwise negate the current element and append it to the recursed.
Essayons d'abord à cette coupe:
(defun negate-seq (seq)
(if (not seq)
(return-from negate-seq))
(if (listp (car seq))
(negate-seq seq)
(list (negate (car seq)) (negate-seq (cdr seq)))))
C'est génial! Sauf que ...
(negate-seq '(1 2)) ==> (-1 (-2 NIL))
Et ...
(negate-seq '(1 (1 2 -3))) ==> STACK OVERFLOW!
Oh boy. Nous avons des problèmes maintenant. Tout d'abord, essayons un cons
au lieu d'un list
. Cela nettoie le problème de la liste imbriquée étrange.
Il est évident que nous sommes dans une boucle de récursion infinie. Cela ne devrait pas être possible, car nous avons la garde not seq
. Ok, alors essayons un débogage. J'utilise CLISP, et je peux tracer avec des arguments:
(trace 'negate-seq)
puis,
(negate-seq '(1 (1 2 -3)))
Tout à coup, je vois une explosion de
1621. Trace: (NEGATE-SEQ '((1 2 -3)))
1622. Trace: (NEGATE-SEQ '((1 2 -3)))
1623. Trace: (NEGATE-SEQ '((1 2 -3)))
1624. Trace: (NEGATE-SEQ '((1 2 -3)))
Crikey, j'ai oublié mon cdr et Contre le cas de liste! Hmmmm.
Essayons:
(defun negate-seq (seq)
(if (not seq)
(return-from negate-seq))
(if (listp (car seq))
(cons (negate-seq (car seq))
(negate-seq (cdr seq)))
(cons (negate (car seq)) (negate-seq (cdr seq)))))
Recurse pour la voiture, récuser sur la voiture, les contre ensemble, nous pourrions être à quelque chose.
(negate-seq '(1 (1 2 -3))) => (-1 (-1 -2 NIL)
Hmmmm. Jetons un coup d'oeil à la trace.
- Trace: (Negate-SEQ '(1 (1 2 -3)))
- Trace: (Negate-SEQ' ((1 2 -3)))
- Trace: (nions-SEQ '(1 2 -3))
- Trace: (negate-SEQ' (2 -3))
- Trace: (negate-SEQ « (-3))
- Trace: (NEGATE- SEQ 'NIL)
- Trace: NEGATE-SEQ ==> NIL
- Trace: NEGATE-SEQ ==> (NIL)
- Trace: NEGATE-SEQ ==> (-2 NIL)
- Trace: NEGATE-SEQ ==> (-1 -2 NIL)
- trace: (SEQ nions-NIL)
- trace: nEGATE-SEQ ==> NIL
- trace: nEGATE-SEQ ==> ((-1 -2 NIL))
- trace: nEGATE-SEQ = => (-1 (-1 -2 NIL))
Je répète e jusqu'à ce que le -3, alors ... il tombe? Impair. Ah! Je saisis continuellement le CDR des choses. Un CDR est toujours une liste. (cdr '(-3)) est nul!
Voyons voir ....
(beaucoup farfouiller)
Négation retourne nul sur positif. D'oh.
(defun negate (n)
(if (> n 0)
(- 0 n)
n))
(defun negate-seq (seq)
"Written by Paul Nathan"
(if (not seq)
(return-from negate-seq))
(if (listp (car seq))
(cons (negate-seq (car seq))
(negate-seq (cdr seq)))
(cons (negate (car seq))
(negate-seq (cdr seq)))))
Salut, Il manque une parenthèse ouvrante pour votre expression de test Cond. (cond (listp a ... => (cond ((listp a ... – juanitofatas