Apa perbedaan antara "set", "setq", dan "setf" di Common Lisp?
common-lisp
Richard Hoskins
sumber
sumber
Jawaban:
Awalnya, di Lisp, tidak ada variabel leksikal - hanya variabel dinamis. Dan tidak ada SETQ atau SETF, hanya fungsi SET.
Apa yang sekarang ditulis sebagai:
ditulis sebagai:
yang akhirnya disingkat menjadi SETQ (SET Dikutip):
Kemudian variabel leksikal terjadi, dan SETQ menjadi digunakan untuk penugasan kepada mereka juga - jadi itu bukan lagi pembungkus sederhana di sekitar SET.
Kemudian, seseorang menemukan SETF (SET Field) sebagai cara umum untuk menetapkan nilai ke struktur data, untuk mencerminkan nilai-l bahasa lainnya:
akan ditulis sebagai
Untuk simetri dan generalisasi, SETF juga menyediakan fungsionalitas SETQ. Pada titik ini, sudah benar untuk mengatakan bahwa SETQ adalah primitif tingkat rendah, dan SETF operasi tingkat tinggi.
Kemudian makro simbol terjadi. Agar makro simbol dapat bekerja secara transparan, disadari bahwa SETQ harus bertindak seperti SETF jika "variabel" yang ditugaskan adalah makro simbol:
Jadi kita tiba di hari ini: SET dan SETQ adalah sisa-sisa dialek yang lebih tua, dan mungkin akan di-boot dari penerus Common Lisp.
sumber
f
sebenarnya singkatan dari function , bukan field (atau form , dalam hal ini), dan memberikan referensi, jadi sementara setf untuk field masuk akal, sepertinya itu mungkin tidak benar.set
adalah fungsi. Dengan demikian tidak mengenal lingkungan.set
tidak dapat melihat variabel leksikal. Ia hanya dapat mengatur nilai simbol dari argumennya.setq
tidak "diatur dikutip" lagi. Fakta bahwa itusetq
adalah bentuk khusus, bukan makro menunjukkan itu.sumber
(setq ls '(((1))))
,(setf (car (car (car ls))) 5)
adalah perilaku tidak terdefinisi, karena nilails
konstan (seperti memodifikasi string literal dalam C). Setelah itu(setq ls (list (list (list 1))))
,(setf (car (car (car ls))) 5)
bekerja sepertils->val->val->val = 5
di C.setq
hanya sepertiset
dengan argumen pertama yang dikutip -(set 'foo '(bar baz))
sama seperti(setq foo '(bar baz))
.setf
, di sisi lain, memang halus - itu seperti "tipuan". Saya menyarankan http://www.nano.com/lisp/cmucl-tutorials/LISP-tutorial-16.html sebagai cara yang lebih baik untuk memulai memahaminya daripada jawaban apa pun di sini yang dapat memberikan ... singkatnya, bagaimanapun,setf
mengambil argumen pertama sebagai "referensi", sehingga mis(aref myarray 3)
akan bekerja (sebagai argumen pertama untuksetf
) untuk mengatur item di dalam array.sumber
Anda dapat menggunakan
setf
sebagai penggantiset
atausetq
tidak sebaliknya karenasetf
juga dapat mengatur nilai elemen individual dari suatu variabel jika variabel tersebut memiliki elemen individual. Lihat contoh di bawah ini:Keempat contoh akan menetapkan daftar (1, 2, 3) ke variabel bernama foo.
setf
memiliki kemampuan tambahan untuk mengatur anggota daftarfoo
ke nilai baru.Namun, Anda bisa mendefinisikan makro simbol yang merepresentasikan satu item di dalamnya
foo
Anda dapat menggunakan
defvar
jika Anda belum mendefinisikan variabel dan tidak ingin memberikan nilai sampai nanti dalam kode Anda.sumber
Orang dapat memikirkan
SET
danSETQ
menjadi konstruksi tingkat rendah.SET
dapat mengatur nilai simbol.SETQ
dapat mengatur nilai variabel.Kemudian
SETF
adalah makro, yang menyediakan berbagai macam pengaturan hal: simbol, variabel, elemen array, slot contoh, ...Untuk simbol dan variabel orang dapat berpikir seolah-olah
SETF
mengembang keSET
danSETQ
.Jadi
SET
danSETQ
digunakan untuk mengimplementasikan beberapa fungsiSETF
, yang merupakan konstruksi yang lebih umum. Beberapa jawaban lain memberi tahu Anda kisah yang sedikit lebih rumit, ketika kita memperhitungkan makro simbol.sumber
Saya ingin menambahkan jawaban sebelumnya bahwa setf adalah makro yang memanggil fungsi tertentu tergantung pada apa yang diteruskan sebagai argumen pertama. Bandingkan hasil ekspansi makro setf dengan berbagai jenis argumen:
Untuk beberapa jenis argumen "fungsi setf" akan dipanggil:
sumber