Come valutare le variabili prima di aggiungerle a un elenco?


30

Il seguito ovviamente non funziona e quindi questa domanda.

Come posso correggere il codice seguente in modo che il valore di somelistdiventi '(("abc" . 123))?

(setq x "abc")
(setq y 123)
(setq somelist nil)
(add-to-list 'somelist '(x . y))

5
Hai provato il quasiquoting? Prova `(,x . ,y).
Dan

Ah, è quello che mi sono perso. Non sapevo per cosa Google :). Ho provato (add-to-list 'somelist '(,x . ,y))ma ho dimenticato il backquote.
Kaushal Modi,

Le domande considerate duplicati di questo si ripetono molto spesso. Qualcuno può trovare un modo per rendere più chiaro ai principianti che questa domanda / risposta è ciò che stanno cercando? Sospetto che parte del problema sia che il titolo di questa domanda ha senso solo se conosci già la causa principale del problema (ovvero conosci la risposta). Sto cercando di immaginarmi come un utente che non ha idea che le variabili debbano essere valutate e ancor meno di un'idea del significato della "citazione", ma mi sto svuotando. @Ha disegnato?
Stefan,

@stefan: a differenza del caso in cui è presente un messaggio di errore (che può essere utilizzato nel titolo della domanda di una comunità Q + A), l'errore, se presente, derivante dalla citazione di qualcosa che deve essere valutato (e questo è un particolare caso del genere) può essere molto distante dal sito del preventivo. Più comunemente, non c'è nessun errore (Emacs) - solo un comportamento che non corrisponde a ciò che l'utente voleva.
Estratto il

@Stefan: Non mi viene in mente il titolo di una grande domanda. Ma potremmo almeno formulare una domanda che la affronti direttamente, incluso forse un caso "normale" che richiede solo la rimozione di un segno di virgolette e un caso che richiede quasi la citazione. Un buon Q, che copre tali casi, e una buona risposta che li copre, sarebbe utile. Ma per quanto riguarda la ricerca di Q che sono duplicati: senza un messaggio di errore nel titolo Q è necessario leggere l'intera domanda e sapere come trovare il duplicato a cui puntare.
Estratto il

Risposte:


30

Il problema generale è che è necessario xed yessere valutati prima che vengano inseriti somelist. Il problema con l' elenco citato (con 'come sintassi del lettore) è che quoteè una forma speciale che non valuta il suo argomento. Secondo la dotstring:

(quote ARG)

Restituisce l'argomento, senza valutarlo. (quote x)rese x. Attenzione: quotenon costruisce il suo valore di ritorno, ma restituisce semplicemente il valore che è stato pre-costruito dal lettore Lisp ...

Quindi, è necessario backquote o utilizzare una funzione che valuta gli argomenti.

Il backquoting consente di valutare selettivamente gli elementi di un elenco backquoted con la ,sintassi:

(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"))

In alternativa, è possibile utilizzare cons(come @tarsius suggerisce nella sua risposta) oppure, per un numero arbitrario di elementi, 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"))

Quale usare dipende da cosa devi fare con gli elementi.


19

Non citare la cella contro, poiché le espressioni tra virgolette non vengono valutate. Questo è esattamente il motivo per cui uno cita - per evitare la valutazione. Ma non è quello che vuoi, quindi non farlo.

Usa invece il modulo che crea una cella contro da due valori valutati, i suoi argomenti.

(cons x y)

Ovviamente puoi anche quasi citare, ma non ha molto senso qui, e sembra peggio. Utilizzare solo `e ,quando ciò migliora la leggibilità, ovvero quando si fa qualcosa di più complesso della costruzione di una cella di contro o dell'aggiunta di un atomo o di un elenco all'inizio di un elenco esistente.

Usando il quasiquoting sembrerebbe così:

`(,x . ,y)

Il che è peggio perché utilizza una sintassi aggiuntiva che non è affatto richiesta in questo caso e offusca che consviene utilizzata.


3
Buon punto conssull'ing. Quasiquoting mi sembra più incentrato sul controllo approfondito dei contenuti dell'elenco piuttosto che sulla leggibilità, ma sono d'accordo sul fatto che il caso d'uso abbia senso cons.
Dan

La ringrazio per la risposta. È stato un grande momento TIL per me. Mettevo ciecamente le virgolette prima delle liste e dei contro.
Kaushal Modi,

@ Dan, beh sì - e no. Quasiquoting non può fare tutto ciò che non si poteva fare con un solo cons, liste nconc. Tranne essere più carino. È lo zucchero sintattico che è utile quando hai bisogno di un "controllo approfondito del contenuto dell'elenco" (come nel "fare qualcosa di più complesso dell'aggiunta di un atomo o di un elenco all'inizio"). E il vantaggio aggiuntivo dell'uso di quello zucchero sintattico è: la leggibilità. Quasiquoting non ti offre un controllo più preciso, ma ti consente di fare la stessa cosa con meno bug nel tentativo iniziale. :-)
tarsius
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.