Tengo lo siguiente:
(setq some-variable "less")
Estoy confundido por qué tengo que usar la comilla simple con boundp
pero no con bound-and-true-p
.
Ejemplo 1:
(when (boundp 'some-variable)
(message "some-variable is %s" some-variable))
Resultado:
"alguna variable es menos"
Ejemplo 2a:
(when (bound-and-true-p some-variable) ;; Note that using single-quote causes error
(message "some-variable is %s" some-variable))
Resultado:
"alguna variable es menos"
Ejemplo 2b:
(when (bound-and-true-p 'some-variable) ;; Note that using single-quote causes error
(message "some-variable is %s" some-variable))
Resultado:
y: Argumento de tipo incorrecto: symbolp, (entre comillas)
setq
significaset quoted
, y originalmente era una macro que se expandió en(set 'some-variable "less")
. En general, Elisp no es terriblemente coherente con los argumentos entre comillas y sin comillas, pero cualquier función (no macro) que necesite interactuar con una variable en lugar de un valor tomará su argumento entre comillas (setq
siendo una excepción importante).bound-and-true-p
es una estúpida macro. O más bien, su nombre es estúpido. El 99,99% de las veces que quieres hacerlo(and (boundp 'FOO) FOO)
lo haces para usar el valor deFOO
. No lo haces solo para obtener un valor de verdad. (1) La macro no es necesaria: el código que reemplaza es trivial y pequeño. (2) El nombre es engañoso: se trata del valor de la variable, no solo de probar si el valor de la variable es o nonil
.Respuestas:
Respuesta corta
Si está tratando de usar la variable en sí, entonces use
'some-variable
. Si está intentando usar el valor almacenado en la variable, usesome-variable
.Explicación
Para la definición del manual, consulte el manual .
'
y(quote ...)
ambos realizan el mismo propósito en emacs-lisp.El propósito de esto es pasar la forma no evaluada al entorno circundante en lugar de evaluarla.
En su ejemplo, suponga que tenemos el siguiente más arriba
Luego la evaluación es la siguiente:
Mientras que sin una cita:
Lisp evalúa los formularios a medida que se alcanzan, citando el formulario que evita la evaluación para que se pase la variable real (o la lista, o el nombre de la función).
fuente
bound-and-truep
y la pregunta era por qué tengo que citar cuando lo usoboundp
pero no cuando lo usobound-and-truep
.boundp
requerir un símbolo (sin evaluar) ybound-and-truep
necesitar el valor de la variable en los puntos (editado después de la respuesta inicial)Un símbolo que se encuentra en una posición sin función se trata como el nombre de una variable. In
(function variable)
function
está en posición de función (después del paréntesis de apertura) yvariable
no lo está. A menos que las variables citadas explícitamente se reemplacen con sus valores.Si
(boundp my-variable)
tuviera que escribir eso significaría "es el símbolo que se almacena en el valor de la variablemy-variable
vinculada como una variable" y no "es el símbolomy-variable
vinculado como una variable.Entonces, ¿por qué se
bound-and-truep
comporta de manera diferente?Esta es una macro y las reglas normales de evaluación (función) no se aplican aquí, las macros son libres de decidir si se evalúan sus argumentos y cuándo. Lo que las macros realmente hacen es de alguna manera transformar los argumentos y devolver el resultado como una lista, que luego se evalúa. La transformación y la evaluación final ocurren en diferentes momentos, llamados tiempo de macroexpansión y tiempo de evaluación.
Así es
bound-and-true-p
como se ve la definición de :Esto usa macros de lector que son diferentes de las macros de lisp (más sobre eso a continuación). Para no complicar esto aún más, no usemos ninguna macro de lector:
Si tú escribes
que primero se "traduce" a
y luego se evalúa devolviendo
nil
simy-variable
no esboundp
o de lo contrario el valor demy-variable
(que por supuesto también puede sernil
).Es posible que hayas notado que la expansión no fue
como podríamos haber esperado
quote
es una forma especial, no una macro o función. Al igual que las macros, las formas especiales pueden hacer lo que sea con sus argumentos. Esta forma especial en particular simplemente devuelve su argumento, aquí un símbolo, en lugar del valor variable del símbolo. Ese es en realidad el único propósito de esta forma especial: ¡evitar la evaluación! Las macros no pueden hacer eso por sí mismas, necesitan usarlasquote
para hacerlo.Entonces, ¿qué pasa
'
? Es una macro lectora , que como se mencionó anteriormente no es lo mismo que una macro lisp . Mientras que las macros se usan para transformar código / datos, las macros de lector se usan antes cuando se lee texto para transformar ese texto en código / datos.es una forma corta de
`
utilizado en la definición real debound-and-true-p
también es una macro lectora. Si cita un símbolo como en`symbol
es equivalente a'symbol
, pero cuando se usa para citar una lista como en,`(foo bar ,baz)
se comporta de manera diferente en la medida en que,
se evalúan los formularios con prefijo .es equivalente a
Esto debería responder a la pregunta de por qué los símbolos sin comillas a veces se evalúan (reemplazan con sus valores) y otras no; Las macros pueden usarse
quote
para evitar que un símbolo sea evaluado.¿Pero por qué es
bound-and-true-p
una macro mientrasboundp
que no lo es? Tenemos que poder determinar si los símbolos arbitrarios, que no se conocen hasta el tiempo de ejecución, están vinculados como símbolos. Esto no sería posible si elboundp
argumento se citara automáticamente.bound-and-true-p
se usa para determinar si se define una variable conocida y, en caso afirmativo, usar su valor. Esto es útil si una biblioteca tiene una dependencia opcional en una biblioteca de terceros como en:bound-and-true-p
podría definirse como una función y requerir que se cite el argumento, pero porque está destinado a casos en los que sabe por adelantado qué variable le importa una macro se usó para evitar que tenga que escribir el'
.fuente
Del código fuente de
boundp
:boundp
espera asymbol
como entrada.'some-variable
Es un símbolo de la variablesome-variable
.Del código fuente de
bound-and-true-p
:bound-and-true-p
espera avariable
como entrada.Dentro de la
bound-and-true-p
macro, obtiene el símbolo haciendo(quote ,var)
. Entonces, si la entrada essome-variable
,(quote ,var)
dará como resultado'some-variable
.Pero cuando doy la entrada
'some-variable
abound-and-true-p
, obtengo el error:and: Wrong type argument: symbolp, (quote some-variable)
porque la macro NO espera un símbolo ('some-variable
) en la entrada.fuente
''symbol
Tiene sentido. Significa(quote (quote symbol))
. La razón por la que obtiene un error es que no es un argumento válido paraboundp
.