Eu tenho o abaixo:
(setq some-variable "less")
Estou confuso por que tenho que usar aspas simples com boundp
mas não com bound-and-true-p
.
Exemplo 1:
(when (boundp 'some-variable)
(message "some-variable is %s" some-variable))
Resultado:
"alguma variável é menor"
Exemplo 2a:
(when (bound-and-true-p some-variable) ;; Note that using single-quote causes error
(message "some-variable is %s" some-variable))
Resultado:
"alguma variável é menor"
Exemplo 2b:
(when (bound-and-true-p 'some-variable) ;; Note that using single-quote causes error
(message "some-variable is %s" some-variable))
Resultado:
e: Argumento de tipo incorreto: symbolp, (cite alguma variável)
setq
significaset quoted
, e originalmente foi uma macro que se expandiu para(set 'some-variable "less")
. Em geral, o Elisp não é muito consistente com argumentos entre aspas e não entre aspas, mas qualquer função (não macro) que precise interagir com uma variável em vez de um valor terá seu argumento entre aspas (setq
sendo uma exceção importante).bound-and-true-p
é uma macro estúpida. Ou melhor, seu nome é estúpido. 99,99% do tempo em que você deseja(and (boundp 'FOO) FOO)
fazê-lo para usar o valor deFOO
. Você não faz isso apenas para obter um valor de verdade. (1) A macro não é necessária - o código que substitui é trivial e pequeno. (2) O nome é enganoso - trata-se do valor da variável, não apenas testando se o valor da variável é ou nãonil
.Respostas:
Resposta curta
Se você estiver tentando usar a variável em si, use
'some-variable
. Se você estiver tentando usar o valor armazenado na variável, usesome-variable
.Explicação
Para a definição do manual, consulte o manual .
'
e(quote ...)
ambos executam o mesmo propósito no emacs-lisp.O objetivo disso é passar a forma não avaliada para o ambiente circundante, em vez de avaliá-la.
No seu exemplo, suponha que tivéssemos o seguinte
Em seguida, a avaliação é a seguinte:
Considerando que sem uma citação:
O Lisp avalia os formulários à medida que são alcançados, citando o formulário que você evita a avaliação para que a variável real (ou lista ou nome da função) seja passada.
fonte
bound-and-truep
e a pergunta era por que eu preciso citar ao usar,boundp
mas não ao usarbound-and-truep
.boundp
a necessidade de um símbolo (não avaliada) ebound-and-truep
precisar o valor da variável nos pontos de bala (editado em após a resposta inicial)Um símbolo que está na posição de não função é tratado como o nome de uma variável. In
(function variable)
function
está na posição da função (após o parêntese de abertura) evariable
não está. A menos que variáveis citadas explicitamente sejam substituídas por seus valores.Se você escrever,
(boundp my-variable)
isso significaria "é o símbolo armazenado no valor da variávelmy-variable
vinculada como variável" e não "é o símbolomy-variable
vinculado como variável.Então, por que
bound-and-truep
se comporta de maneira diferente?Essa é uma macro e as regras de avaliação normal (de função) não se aplicam aqui; as macros são livres para decidir se e quando seus argumentos serão avaliados. O que as macros realmente fazem é de alguma forma transformar os argumentos e retornar o resultado como uma lista, que é então avaliada. A transformação e a avaliação final ocorrem em momentos diferentes, chamados macroexpansão e tempo da avaliação.
É assim que a definição de se
bound-and-true-p
parece:Isso usa macros de leitor diferentes das macros lisp (mais sobre isso abaixo). Para não complicar ainda mais, não vamos usar macros de leitor:
Se você escrever
que é primeiro "traduzido" para
e então isso é avaliado, retornando
nil
semy-variable
não forboundp
ou então o valor demy-variable
(que, é claro, também pode sernil
)Você deve ter notado que a expansão não foi
como poderíamos esperar.
quote
é uma forma especial, não uma macro ou função. Como macros, formas especiais podem fazer o que quiser com seus argumentos. Essa forma especial em particular simplesmente retorna seu argumento, aqui um símbolo, em vez do valor variável do símbolo. Na verdade, esse é o único objetivo deste formulário especial: impedir a avaliação! As macros não podem fazer isso sozinhas, elas precisam usáquote
- las .Então, o que se passa
'
? É uma macro de leitor que, como mencionado acima, não é o mesmo que uma macro lisp . Enquanto as macros são usadas para transformar código / dados, as macros do leitor são usadas anteriormente ao ler texto para transformar esse texto em código / dados.é uma forma curta para
`
usado na definição real debound-and-true-p
also é uma macro de leitor. Se citar um símbolo, como`symbol
nele é equivalente a'symbol
, mas quando é usado para citar uma lista, como`(foo bar ,baz)
se comporta de maneira diferente, na medida em que os formulários prefixados,
são avaliados.é equivalente a
Isso deve responder à pergunta por que símbolos não citados são algumas vezes avaliados (substituídos por seus valores) e outras vezes não; macros podem ser usadas
quote
para impedir que um símbolo seja avaliado.Mas por que
bound-and-true-p
uma macroboundp
é enquanto não é? Temos que poder determinar se símbolos arbitrários, que não são conhecidos até o tempo de execução, estão vinculados como símbolos. Isso não seria possível se oboundp
argumento fosse automaticamente citado.bound-and-true-p
é usado para determinar se uma variável conhecida está definida e, em caso afirmativo, use seu valor. Isso é útil se uma biblioteca tiver uma dependência opcional em uma biblioteca de terceiros, como em:bound-and-true-p
pode ser definido como uma função e exigir que o argumento seja citado, mas porque ele se destina a casos em que você sabe de antemão qual variável se preocupa com uma macro foi usada para evitar que você digite'
.fonte
Do código fonte de
boundp
:boundp
espera asymbol
como a entrada.'some-variable
é um símbolo para a variávelsome-variable
.Do código fonte de
bound-and-true-p
:bound-and-true-p
espera avariable
como a entrada.Dentro da
bound-and-true-p
macro, ele obtém o símbolo fazendo(quote ,var)
. Portanto, se a entrada forsome-variable
,(quote ,var)
resultará em'some-variable
.Mas quando dou a entrada
'some-variable
parabound-and-true-p
, recebo o erro:and: Wrong type argument: symbolp, (quote some-variable)
porque a macro NÃO está esperando um símbolo ('some-variable
) na entrada.fonte
''symbol
faz sentido. Isso significa(quote (quote symbol))
. A razão pela qual você recebe um erro é que não é um argumento válidoboundp
.