2009-09-06 12 views
7

Soy nuevo en lisp y estoy escribiendo algunos programas sencillos para familiarizarme con él. Una de las cosas que hago es escribir una versión recursiva e iterativa de un método factorial. Sin embargo, me he encontrado con un problema y no puedo resolverlo.Aviso Lisp: xx no está declarado ni enlazado, se tratará como si hubiera sido declarado ESPECIAL

vi un error similar al Lisp: CHAR is neither declared nor bound pero no se alcanza una solución en realidad, aparte de la OP dio cuenta de que cometió un "error de escritura". En REPL puedo usar la función setf y funciona bien. También estoy usando LispBox con emacs. ¡Apreciaria cualquier sugerencia!

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

ADVERTENCIA en TI-HECHO: RESULTADO no se declara ni obligado, será tratado como si se tratara de declarar ESPECIAL.

+1

Ver http://www.cs.cmu.edu/Groups/AI /html/faqs/lang/lisp/part1/faq-doc-4.html, especialmente el ejemplo "BUENO". Aquí la gente es muy amigable, pero tu código es más fácil de leer si está sangrado más como el típico código Lisp. ¡Aclamaciones! – Alec

Respuesta

5

Es necesario vincular el 'resultado' variable - con ayuda de 'dejar', por ejemplo - antes de comenzar a utilizarlo:

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

Para saber más detalles es posible que desee leer this ...

+0

Oh, ya veo. También intenté 'dejar' antes, pero lo estaba usando como si fuera setf, y no incluí el bucle de dimesis dentro del paréntesis de let. Supongo que tiene que ver con el alcance o algo así. Gracias por ayudar a todos! – Aaron

+0

En serio, sangra tu código correctamente. –

+0

Dado que soy principalmente un programador de Java, puede ver fácilmente por qué bajé el paréntesis (viéndolos como nada más que corchetes). Desde entonces, me he acostumbrado a poner a los padres en una línea, gracias a los ejemplos presentados aquí, por lo que "en serio" no es tan importante. Gracias anway :) – Aaron

5

En Lisp, las variables locales deben declararse explícitamente con LET u otras formas que creen variables locales. Eso difiere de, por ejemplo, Python o JavaScript donde la asignación a la variable crea la variable en el alcance léxico actual.

Su ejemplo puede reescribirse así:

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

Un comentario fuera de tema: no hay ningún punto en poner paréntesis de cierre en líneas separadas.

6

Hay algunas cosas mal o no tan buen estilo 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 

una posible versión:

(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

Gracias por las sugerencias! Sí, me di cuenta de que los dotimes comenzaban desde 0 y que si no los incrementaba en la multiplicación, siempre regresarían a 0 ... Su loop parece más fácil de leer. Creo que puse paréntesis en cada línea así porque aún estoy acostumbrado a llaves de C++/java, pero intentaré adoptar tu práctica para lisp. Oops, sí, pasé por alto el regreso, ¡gracias por señalar estas cosas! – Aaron

Cuestiones relacionadas