2011-10-16 18 views
9

EDITAR: Cambié el código de ejemplo después de la primera respuesta porque se me ocurrió una versión simple que plantea las mismas preguntas.Alcance de Lisp común (dinámico frente a léxico)

Actualmente estoy aprendiendo las propiedades de alcance de Common Lisp. Después de pensar que tenía una comprensión sólida, decidí codificar algunos ejemplos de los que podía predecir el resultado, pero aparentemente estaba equivocado. Tengo tres cuestión, cada uno relativo a un ejemplo a continuación:

Ejemplo 1:

(defmethod fun1 (x) 
    (print x) 
    (fun2)) 

(defmethod fun2() 
    (print x)) 

(fun1 5) 

de salida:

5 
*** - EVAL: variable X has no value 

Pregunta: Esto tiene sentido. x tiene un alcance estático y fun2 no tiene forma de encontrar el valor de x sin que se pase explícitamente.

Ejemplo 2:

(defvar x 100) 

(defmethod fun1 (x) 
    (print x) 
    (fun2)) 

(defmethod fun2() 
    (print x)) 

(fun1 5) 

Salida:

5 
5 

Pregunta: No entiendo por qué x es repentinamente visible para Fun2 con el valor que se dio fun1, en lugar de tener un valor de 100 ...

Ejemplo 3:

(setf x 100) 

(defmethod fun1 (x) 
    (print x) 
    (fun2)) 

(defmethod fun2() 
    (print x)) 

(fun1 5) 

Salida:

5 
100 

Pregunta: ¿Debo pasar por alto estos resultados desde llamando setf en una variable no declarada es aparentemente indefinido? Esto pasa a ser lo que se espera en mi segundo ejemplo ...

Cualquier idea sería muy apreciada ...

+0

Aquí es mi explicación ingenua Después de jugar un poco ... que me haga saber si estoy cerca .. Exmaple 1: necesita ninguna explicación Ejemplo 2: declarar x como una variable dinámica hace que todas las instancias de x que debe buscarse en tiempo de ejecución en la pila de variables dinámicas, lo que causaría que fun2 heredara el valor de x de fun1, a pesar de no ser una variable dinámica. Ejemplo 3: ni idea ... Supongo que es indefinido –

+0

* Las preguntas planteadas son buenas. * Peticiones * es ** malo. ** –

+0

En lugar de DEFMETHOD, use DEFUN. Un DEFMETHOD no es necesario en estos ejemplos. DEFUN crea una función simple. DEFMETHOD es para funciones genéricas, donde necesita un poco de despacho. –

Respuesta

18

Los efectos de establecer una variable no definida usando SETF no está definido en la norma ANSI Common Lisp.

DEFVAR definirá una variable especial. Esta declaración es global y también tiene efecto en los enlaces LET. Esa es la razón por la cual, por convención, estas variables se escriben como *foo*. Si alguna vez ha definido X con DEFVAR, se declara especial y no hay forma de declararlo léxico más tarde.

LET proporciona de forma predeterminada las variables léxicas locales. Si la variable ya fue declarada especial (por ejemplo, debido a un DEFVAR), entonces solo crea un nuevo enlace dinámico local.

actualización

  • Ejemplo 1.

Nada que ver.

  • Ejemplo 2

X ha sido declarado especial. Todos los usos de la variable X ahora usan enlace dinámico. Al llamar a la función, enlaza X a 5. Dinámicamente. Otras funciones ahora pueden acceder a este enlace dinámico y obtener ese valor.

  • Ejemplo 3

Este es un comportamiento indefinido en Common Lisp. Estás configurando una variable no declarada. Lo que sucede entonces depende de la implementación. Su implementación (la mayoría hace algo similar) establece el valor del símbolo de X en 100. En FUN1, X está ligado léxicamente. En FUN2, la evaluación de X recupera el valor del símbolo (o posiblemente el valor enlazado dinámicamente) de X.

Como ejemplo para una implementación que hizo (¿hace?) Algo más: la implementación CMUCL también tendría declarar X en el ejemplo 3 por defecto es especial. Establecer una variable indefinida también lo declara especial.

NOTA

En cumpla con los códigos estándar Common Lisp portátil de las variables globales se definen con defvar y DEFPARAMETER. Ambos declaran que estas variables son especiales. TODOS los usos de estas variables ahora implican un enlace dinámico.

Recuerde:

((lambda (x) 
    (sin x)) 
10) 

es básicamente el mismo que

(let ((x 10)) 
    (sin x)) 

Lo que significa que asociaciones de variables en los enlaces de LET y asociaciones de variables en las llamadas a funciones están funcionando de la misma manera. Si X hubiera sido declarado especial en algún lugar antes, ambos implicarían un enlace dinámico.

Esto se especifica en el estándar Common Lisp. Ver por ejemplo la explicación al SPECIAL declaration.

+0

He actualizado mi publicación original con ejemplos más precisos y preguntas que reflejan lo que estaba teniendo problemas para entender. Específicamente, el comportamiento demostrado en mi segundo ejemplo en comparación con mi primer ejemplo –

+0

¡Gracias por la aclaración! No creo que esperaba que los valores de los parámetros de las funciones se efectuaran de la misma manera que las variables libres normales ... pero supongo que cada mención se trata de la misma manera. –

+1

@ antman8969: el uso de variables es el mismo en todos lados. Lo que es un poco sorprendente es que los parámetros de la función también pueden estar vinculados dinámicamente y que se ven afectados por la definición de variables con DEFVAR. –

Cuestiones relacionadas