tutorial programacion mac lenguaje for common lisp common-lisp

programacion - lisp install



Diferencia entre LET y SETQ? (4)

Deje que casi siempre sea la forma en que se unen las variables dentro de una definición de función, excepto en el caso poco frecuente de que desee que el valor esté disponible para otras funciones en el mismo ámbito.

Me gusta la descripción en el manual de emacs lisp:

let se utiliza para adjuntar o vincular un símbolo a un valor de tal manera que el intérprete Lisp no confunda la variable con una variable del mismo nombre que no sea parte de la función.

Para comprender por qué es necesario dejar un formulario especial, considere la situación en la que posee una casa a la que generalmente se refiere como the house'', as in the sentence, “The house needs painting.” If you are visiting a friend and your host refers to la casa '', es probable que se refiera a su casa, no a la suya, es decir, a una casa diferente.

Si su amigo se está refiriendo a su casa y usted cree que él se está refiriendo a su casa, es posible que tenga alguna confusión. Lo mismo podría suceder en Lisp si una variable que se usa dentro de una función tiene el mismo nombre que una variable que se usa dentro de otra función, y las dos no pretenden referirse al mismo valor. La forma especial de dejar previene este tipo de confusión.

- http://www.gnu.org/software/emacs/manual/html_node/eintr/let.html

Estoy programando en Ubuntu usando GCL. De la documentación sobre Common Lisp de varias fuentes, entiendo que let crear variables locales , y setq establece los valores de las variables existentes . En los casos a continuación, necesito crear dos variables y sumar sus valores.

Usando setq

(defun add_using_setq () (setq a 3) ; a never existed before , but still I''m able to assign value, what is its scope? (setq b 4) ; b never existed before, but still I''m able to assign value, what is its scope? (+ a b))

Usando let

(defun add_using_let ( ) (let ((x 3) (y 4)) ; creating variables x and y (+ x y)))

En ambos casos parece que logro el mismo resultado; ¿ setq es la diferencia entre usar setq y let aquí? ¿Por qué no puedo usar setq (ya que es sintácticamente fácil) en todos los lugares donde necesito usar let ?


(setq xy) asigna un nuevo valor y a la variable designada por el símbolo x , definiendo opcionalmente una nueva variable de nivel de paquete 1 . Esto significa que después de llamar a add_using_setq tendrá dos nuevas variables de nivel de paquete en el paquete actual.

(add_using_setq) (format t "~&~s, ~s" a b)

imprimirá 3 4 - improbable el resultado deseado.

Para contrastar eso, cuando usa let , solo asigna nuevos valores a las variables designadas por los símbolos durante la duración de la función, por lo que este código generará un error:

(add_using_let) (format t "~&~s, ~s" a b)

Piense en let que sea equivalente al siguiente código:

(defun add-using-lambda () (funcall (lambda (a b) (+ a b)) 3 4))

Además, realmente desea ver el código escrito por otros programadores para tener una idea de cómo nombrar o dar formato a las cosas. Además de ser tradicional, también tiene algunas propiedades tipográficas que no quiere perder.

1 Este comportamiento no es estándar, pero esto es lo que sucede en muchas implementaciones populares. Independientemente de que sea bastante predecible, se considera una mala práctica por otras razones, en su mayoría todas las mismas preocupaciones que lo desanimarían a usar variables globales.


setq asigna un valor a una variable, mientras que let introduce nuevas variables / vinculaciones. Por ejemplo, mira lo que pasa en

(let ((x 3)) (print x) ; a (let ((x 89)) (print x) ; b (setq x 73) (print x)) ; c (print x)) ; d 3 ; a 89 ; b 73 ; c 3 ; d

El margen externo crea una variable local x , y el margen interno crea otra variable local que hace sombra al interno. Tenga en cuenta que el uso de let para sombrear la variable no afecta el valor de la variable sombreada; la x en la línea d es la x introducida por el permiso externo, y su valor no ha cambiado. setq solo afecta la variable con la que se llama. Este ejemplo muestra setq usado con variables locales, pero también puede ser con variables especiales (es decir, con un alcance dinámico, y generalmente definido con defparameter o defvar

CL-USER> (defparameter *foo* 34) *FOO* CL-USER> (setq *foo* 93) 93 CL-USER> *foo* 93

Tenga en cuenta que setq no crea variables (de forma portátil), mientras que let , defvar , defparameter , & c. hacer. El comportamiento de setq cuando se llama con un argumento que no es una variable (aún) no está definido, y depende de una implementación decidir qué hacer. Por ejemplo, SBCL se queja en voz alta:

CL-USER> (setq new-x 89) ; in: SETQ NEW-X ; (SETQ NEW-X 89) ; ; caught WARNING: ; undefined variable: NEW-X ; ; compilation unit finished ; Undefined variable: ; NEW-X ; caught 1 WARNING condition 89

Por supuesto, las mejores maneras de comprender mejor estos conceptos son leer y escribir más código Lisp (que viene con el tiempo) y leer las entradas en HyperSpec y seguir las referencias cruzadas, especialmente las entradas del glosario. Por ejemplo, las breves descripciones de HyperSpec para setq y let incluir:

  • SETQ

    Asigna valores a las variables .

  • LET

    permite y permite * crear nuevos bindings variables y ejecutar una serie de formularios que utilizan estos enlaces.

Es posible que desee leer más sobre variables y enlaces. let y let* también tenga algún comportamiento especial con variables dinámicas y declaraciones special (pero probablemente no necesite saberlo por un tiempo), y en ciertos casos (que probablemente no necesite saber por un tiempo) ) cuando una variable no es realmente una variable, setq es realmente equivalente a setf . El HyperSpec tiene más detalles.

Hay algunas preguntas no bastante duplicadas sobre el Desbordamiento de pila que, sin embargo, pueden ayudar a comprender el uso de los diversos operadores de definición y asignación de variables disponibles en Common Lisp:

  • setq y defvar en lisp
  • ¿Cuál es la diferencia entre defvar, defparameter, setf y setq?
  • Asignando variables con setf, defvar, let y scope
  • En Lisp, ¿cómo soluciono "Advertencia: Especialmente asumido?" (re: usando setq en variables indefinidas)
  • ¿Diferencia entre let * y set? en Lisp Común

  • SETQ

puede obtener el valor del símbolo fuera del alcance, siempre y cuando Lisp todavía se esté ejecutando. (Asigna el valor al símbolo).

  • DEJAR

no puede obtener el valor del símbolo definido con LET después de que Lisp haya terminado de evaluar el formulario. (enlaza el valor al símbolo y crea un nuevo enlace al símbolo)

Considere el siguiente ejemplo:

;; with setq CL-USER> (setq a 10) CL-USER> a 10 ;; with let CL-USER> (let ((b 20)) (print b)) CL-USER> 20 CL-USER> b ; it will fail ; Evaluation aborted on #<UNBOUND-VARIABLE B {1003AC1563}>. CL-USER>