Bagaimana cara mengevaluasi variabel sebelum menambahkannya ke daftar?

30

Di bawah ini jelas tidak berfungsi dan karenanya pertanyaan ini.

Bagaimana cara memperbaiki kode di bawah ini sehingga nilai somelistmenjadi '(("abc" . 123))?

(setq x "abc")
(setq y 123)
(setq somelist nil)
(add-to-list 'somelist '(x . y))
Kaushal Modi
sumber
5
Sudahkah Anda mencoba quasiquoting? Coba `(,x . ,y).
Dan
Ah, itu yang saya lewatkan. Saya tidak tahu untuk apa google :). Saya mencoba (add-to-list 'somelist '(,x . ,y))tetapi lupa dengan backquote.
Kaushal Modi
Pertanyaan yang dianggap sebagai duplikat dari pertanyaan ini sangat sering muncul. Dapatkah seseorang menemukan cara untuk membuatnya lebih jelas bagi pemula bahwa pertanyaan / jawaban ini adalah yang mereka cari? Saya menduga bagian dari masalahnya adalah bahwa judul pertanyaan ini hanya masuk akal jika Anda sudah tahu akar penyebab masalahnya (yaitu Anda tahu jawabannya). Saya mencoba membayangkan diri saya sebagai pengguna yang tidak tahu bahwa variabel perlu dievaluasi dan bahkan lebih sedikit dari ide apa arti "kutipan", tetapi semakin kosong. @Drew?
Stefan
@stefan: Berbeda dengan kasus di mana ada pesan kesalahan (yang dapat digunakan dalam judul pertanyaan komunitas Q + A), kesalahan, jika ada, dihasilkan dari mengutip sesuatu yang perlu dievaluasi (dan ini khusus kasus itu) bisa jauh dari situs yang mengutip. Lebih umum, tidak ada kesalahan (Emacs) - hanya perilaku yang tidak sesuai dengan apa yang diinginkan pengguna.
Drew
@Stefan: Tidak ada judul pertanyaan besar yang terlintas dalam pikiran untuk ini. Tapi setidaknya kita bisa merumuskan pertanyaan yang menangani secara langsung, termasuk mungkin kasus "normal" yang menyerukan hanya menghapus tanda kutip dan kasus yang menyerukan quasiquoting. Q yang baik, yang mencakup kasus-kasus seperti itu, dan jawaban yang bagus untuk mereka, akan sangat membantu. Tetapi untuk menemukan Qs yang merupakan duplikat: tanpa pesan kesalahan dalam judul Q itu membutuhkan membaca seluruh pertanyaan dan mengetahui bagaimana menemukan duplikat untuk menunjuk.
Drew

Jawaban:

30

Masalah umum adalah bahwa Anda perlu xdan ydievaluasi sebelum dimasukkan somelist. Masalah dengan daftar yang dikutip (dengan 'sintaks sebagai pembaca) adalah quotebentuk khusus yang tidak mengevaluasi argumennya. Menurut dokumen itu:

(quote ARG)

Kembalikan argumen, tanpa mengevaluasinya. (quote x)hasil panen x. Peringatan: quotetidak membangun nilai kembalinya, tetapi hanya mengembalikan nilai yang telah dibangun sebelumnya oleh pembaca Lisp ...

Oleh karena itu, Anda perlu mengutip atau menggunakan fungsi yang mengevaluasi argumen.

Backquoting memungkinkan Anda untuk mengevaluasi elemen daftar backquoted selektif dengan ,sintaks:

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

Sebagai alternatif, Anda dapat menggunakan cons(sebagai @tarsius menyarankan dalam jawabannya) atau, untuk jumlah sewenang-wenang elemen, 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"))

Yang digunakan tergantung pada apa yang perlu Anda lakukan dengan elemen.

Dan
sumber
19

Jangan mengutip sel kontra, karena ekspresi yang dikutip tidak dievaluasi. Itulah sebabnya seseorang mengutip - untuk mencegah evaluasi. Tapi bukan itu yang Anda inginkan, jadi jangan.

Alih-alih menggunakan formulir yang membuat sel kontra dari dua nilai yang dievaluasi, argumennya.

(cons x y)

Tentu saja Anda juga dapat kuasiquote tetapi itu tidak masuk akal di sini, dan terlihat lebih buruk. Hanya gunakan `dan ,ketika itu meningkatkan keterbacaan, yaitu ketika melakukan sesuatu yang lebih kompleks daripada membangun sel kontra atau menambahkan atom atau daftar di awal beberapa daftar yang ada.

Menggunakan quasiquoting akan terlihat seperti ini:

`(,x . ,y)

Yang lebih buruk karena menggunakan sintaks tambahan yang tidak diperlukan sama sekali dalam hal ini dan mengaburkan yang conssedang digunakan.

tarsius
sumber
3
Poin bagus tentang consing. Quasiquoting menurut saya lebih tentang kontrol konten daftar yang halus daripada mudah dibaca, tapi saya setuju bahwa use case masuk akal cons.
Dan
Terima kasih atas jawaban Anda. Itu adalah momen TIL yang hebat bagi saya. Saya secara membabi buta menempatkan kutipan di depan daftar dan kontra.
Kaushal Modi
@ Dan, baik ya - dan tidak. Quasiquoting tidak bisa melakukan apa pun yang Anda tidak bisa melakukan hanya dengan cons, list, dan nconc. Kecuali menjadi lebih cantik. Ini adalah gula sintaksis yang berguna ketika Anda membutuhkan "kendali halus atas isi daftar" (seperti dalam "melakukan sesuatu yang lebih kompleks daripada menambahkan atom atau daftar di awal"). Dan manfaat tambahan menggunakan gula sintaksis adalah: keterbacaan. Quasiquoting tidak memberi Anda kontrol tambahan yang lebih halus - itu hanya memungkinkan Anda untuk melakukan hal yang sama dengan lebih sedikit bug dalam upaya awal. :-)
tarsius