2009-09-06 5 views
7

Je suis nouveau à lisp et j'écris quelques programmes simples pour mieux me familiariser avec lui. Une des choses que je fais est d'écrire une version récursive et itérative d'une méthode factorielle. Cependant, j'ai rencontré un problème et n'arrive pas à le résoudre.Avertissement Lisp: xx n'est ni déclaré ni lié, il sera traité comme s'il avait été déclaré SPECIAL

je vis une erreur semblable à Lisp: CHAR is neither declared nor bound mais n'a pas été réellement parvenu à une solution autre que l'OP se rendit compte qu'il a fait une « erreur de frappe ». Dans le REPL, je peux utiliser la fonction setf et cela fonctionne très bien. J'utilise aussi LispBox avec emacs. J'apprécierais toutes suggestions!

(defun it-fact(num) 
    (setf result 1) 
    (dotimes (i num) 
    (setf result (* result (+ i 1))) 
) 
) 

AVERTISSEMENT IT-FACT: Le résultat est déclaré ni lié, elle sera traitée comme si elle était déclarée spéciale.

+1

Voir http://www.cs.cmu.edu/Groups/AI /html/faqs/lang/lisp/part1/faq-doc-4.html, en particulier l'exemple "GOOD:". Les gens d'ici sont plutôt sympathiques, mais le code est plus facile à lire s'il est en retrait plutôt que le code Lisp typique. À votre santé! – Alec

Répondre

5

Vous devez lier la variable « résultat » - en utilisant « let », par exemple - avant de commencer à l'utiliser:

(defun it-fact(num) 
    (let ((result 1)) 
    (dotimes (i num) 
     (setf result (* result (+ i 1)))))) 

Pour plus de détails, vous pouvez lire this ...

+0

Oh je vois. J'avais déjà essayé 'let', mais je l'utilisais comme s'il était setf, et je n'ai pas inclus la boucle de dotimes dans la parenthèse du let. Je suppose que cela a à voir avec la portée ou quelque chose. Merci à tous pour l'aide! – Aaron

+0

Sérieusement, indentez correctement votre code. –

+0

Depuis que je suis principalement un programmeur java, vous pouvez facilement voir pourquoi j'ai descendu la parenthèse (les voir comme rien de plus que des parenthèses). Je me suis depuis habitué à mettre les parenthèses fermantes sur une ligne grâce aux exemples présentés ici, donc c'est "sérieusement" pas un gros problème. Merci an :) – Aaron

5

En Lisp, les variables locales doivent être explicitement déclarées avec LET ou d'autres formes qui créent des variables locales. Cela diffère de par exemple. Python ou JavaScript où l'affectation à la variable crée la variable dans la portée lexicale actuelle.

Votre exemple peut être réécrite comme ceci:

(defun it-fact(num) 
    (let ((result 1)) 
    (dotimes (i num) 
     (setf result (* result (+ i 1)))))) 

Un commentaire hors-sujet: il est inutile de mettre entre parenthèses la fermeture sur des lignes distinctes.

6

Il y a quelques petites choses mal ou pas si bon style Lisp:

(defun it-fact(num)      ; style: use a space before (
    (setf result 1)      ; bad: variable result is not introduced 
    (dotimes (i num) 
    (setf result (* result (+ i 1)))  ; bad: extra addition in each iteration 
)          ; style: parentheses on a single line 
)          ; bad: no useful return value 

Une version possible:

(defun it-fact (num) 
    (let ((result 1))      ; local variable introduced with LET 
    (loop for i from 1 upto num   ; i starts with 1, no extra addition 
     do (setf result (* result i))) 
    result))        ; result gets returned from the LET 
+2

Merci pour les suggestions! Ouais, je me suis rendu compte que dotimes commençait à partir de 0 et si je ne l'incrémentais pas dans la multiplication il retournerait toujours 0 ... Votre boucle semble plus facile à lire. Je pense que je mets des parenthèses sur chaque ligne comme ça parce que je suis toujours habitué aux accolades de C++/java, mais je vais essayer d'adopter votre pratique pour le lisp. Oups, ouais, j'ai oublié le retour, merci d'avoir signalé ces choses! – Aaron

Questions connexes