Como avaliar as variáveis ​​antes de adicioná-las a uma lista?

30

O abaixo, obviamente, não funciona e, portanto, esta questão.

Como faço para corrigir o código abaixo para que o valor de somelistse torne '(("abc" . 123))?

(setq x "abc")
(setq y 123)
(setq somelist nil)
(add-to-list 'somelist '(x . y))
Kaushal Modi
fonte
5
Você já tentou quasiquotar? Tente `(,x . ,y).
Dan
Ah, foi disso que eu perdi. Eu não sabia o que fazer no google :). Eu tentei, (add-to-list 'somelist '(,x . ,y))mas esqueci a citação.
precisa saber é o seguinte
As perguntas consideradas duplicadas são recorrentes com muita frequência. Alguém pode inventar uma maneira de deixar mais claro para os iniciantes que essa pergunta / resposta é o que eles estão procurando? Eu suspeito que parte do problema é que o título desta pergunta só faz sentido se você já conhece a causa raiz do problema (ou seja, você sabe a resposta). Estou tentando me imaginar como um usuário que não tem idéia de que variáveis ​​precisam ser avaliadas e muito menos do que a "citação" significa, mas estou ficando vazio. @Desenhou?
22418 Stefan #
@stefan: Diferentemente do caso em que há uma mensagem de erro (que pode ser usada no título da pergunta de uma comunidade Q + A), o erro, se houver, resultante da citação de algo que precisa ser avaliado (e isso é um problema particular) caso disso) pode estar muito longe do site da citação. Mais comumente, não há erro (Emacs) - apenas comportamento que não corresponde ao que o usuário queria.
Tirou
@ Stefan: Nenhum grande título de pergunta vem à mente para isso. Mas poderíamos, pelo menos, formular uma pergunta que a lide diretamente, incluindo talvez um caso "normal" que exija apenas a remoção de aspas e um caso que exija quasiquotar. Um bom Q, cobrindo esses casos, e uma boa resposta para eles, seria útil. Mas, como encontrar Qs duplicados: sem uma mensagem de erro no título Q, é necessário ler toda a pergunta e saber como encontrar a duplicata para a qual apontar.
Tirou

Respostas:

30

O problema geral é que você precisa xe ydeve ser avaliado antes de serem inseridos somelist. O problema com a lista citada (com 'sintaxe do leitor) é que quoteé uma forma especial que não avalia seu argumento. De acordo com a doutrina:

(quote ARG)

Retorne o argumento, sem avaliá-lo. (quote x)rendimentos x. Atenção: quotenão constrói seu valor de retorno, mas apenas retorna o valor que foi pré-construído pelo leitor Lisp ...

Portanto, você precisa fazer uma cotação retroativa ou usar uma função que avalie os argumentos.

A cotação retroativa permite avaliar elementos de uma lista de cotações retroativas seletivamente com a ,sintaxe:

(setq x "x-val" y "y-val" z "z-val" somelist nil)
'(x  y z)                            ; => (x y z)
`(x ,y z)                            ; => (x "y-val" z)
(add-to-list 'somelist `(x y ,z))    ; => ((x y "z-val"))

Alternativamente, você pode usar cons(como @tarsius sugere na sua resposta) ou, para um número arbitrário de elementos, list:

(add-to-list 'somelist (cons x y))   ; => (("x-val" . "y-val"))
(setq somelist nil)                  ; reset
(add-to-list 'somelist (list x y z)) ; => (("x-val" "y-val" "z-val"))

Qual usar depende do que você precisa fazer com os elementos.

Dan
fonte
19

Não cite a célula contras, porque as expressões entre aspas não são avaliadas. É exatamente por isso que se cita - para impedir a avaliação. Mas não é isso que você quer, então não faça.

Em vez disso, use o formulário que cria uma célula contras a partir de dois valores avaliados, seus argumentos.

(cons x y)

É claro que você também pode fazer quasiquotes, mas isso não faz muito sentido aqui e parece pior. Use apenas `e ,quando isso melhorar a legibilidade, ou seja, ao fazer algo mais complexo do que construir uma célula contras ou adicionar um átomo ou lista no início de alguma lista existente.

Usando quasiquoting, ficaria assim:

`(,x . ,y)

O que é pior porque usa sintaxe adicional, que não é necessária nesse caso, e ofusca o que consestá sendo usado.

tarso
fonte
3
Bom ponto de vista cons. Quasiquotar me parece mais sobre o controle refinado do conteúdo da lista do que sobre a legibilidade, mas eu concordo que o caso de uso faz sentido cons.
Dan
Obrigado pela sua resposta. Esse foi um ótimo momento para mim. Eu estava cegamente colocando aspas antes de listas e contras.
precisa saber é o seguinte
@ Dan, bem, sim - e não. Quasiquoting não pode fazer nada que você não poderia fazer com apenas cons, liste nconc. Exceto ser mais bonita. É um açúcar sintático que é útil quando você precisa de "controle refinado do conteúdo da lista" (como em "fazer algo mais complexo do que adicionar um átomo ou lista no início"). E o benefício adicional de usar esse açúcar sintático é: legibilidade. A quasiquotagem não fornece um controle mais refinado adicional - apenas permite que você faça a mesma coisa com menos erros na tentativa inicial. :-)
tarsius