Simbol yang berada di posisi non-fungsi diperlakukan sebagai nama variabel. In (function variable) functionadalah dalam fungsi-posisi (setelah tanda kurung buka) dan variabletidak. Kecuali jika variabel yang dikutip secara eksplisit diganti dengan nilainya.
Jika Anda menulis (boundp my-variable)itu berarti "adalah simbol yang disimpan dalam nilai variabel my-variableterikat sebagai variabel" dan bukan "adalah simbol yang my-variableterikat sebagai variabel.
Jadi mengapa bound-and-truepberperilaku berbeda?
Ini adalah makro dan aturan evaluasi normal (fungsi) tidak berlaku di sini, makro bebas untuk memutuskan apakah dan kapan argumen mereka dievaluasi. Apa yang sebenarnya dilakukan makro adalah entah bagaimana mengubah argumen dan mengembalikan hasilnya sebagai daftar, yang kemudian dievaluasi. Transformasi dan evaluasi akhir terjadi pada waktu yang berbeda, yang disebut waktu ekspansi-makro dan waktu evaluasi.
Seperti inilah definisi bound-and-true-ptampilannya:
(defmacro bound-and-true-p (var)
"Return the value of symbol VAR if it is bound, else nil."
`(and (boundp (quote ,var)) ,var))
Ini menggunakan macro pembaca yang berbeda dari macro lisp (lebih lanjut tentang itu di bawah). Untuk tidak mempersulit hal ini lebih lanjut, jangan gunakan makro pembaca apa pun:
(defmacro bound-and-true-p (var)
"Return the value of symbol VAR if it is bound, else nil."
(list 'and (list 'boundp (list 'quote var)) var))
Jika kamu menulis
(bound-and-true-p my-variable)
yang pertama "diterjemahkan" ke
(and (boundp 'my-variable) my-variable)
dan kemudian itu dievaluasi kembali niljika my-variabletidak boundpatau nilai my-variable(yang tentu saja bisa juga nil).
Anda mungkin memperhatikan bahwa ekspansi tidak
(and (boundp (quote my-variable)) my-variable)
seperti yang bisa kita harapkan. quoteadalah bentuk khusus, bukan makro atau fungsi. Seperti makro, bentuk khusus dapat melakukan apa pun dengan argumen mereka. Bentuk khusus khusus ini hanya mengembalikan argumennya, di sini simbol, bukan nilai variabel simbol. Itu sebenarnya satu-satunya tujuan bentuk khusus ini: mencegah evaluasi! Macro tidak dapat melakukannya sendiri, mereka perlu menggunakannya quoteuntuk melakukannya.
Jadi ada apa '? Ini adalah makro pembaca , yang seperti disebutkan di atas tidak sama dengan makro pelat . Sementara makro digunakan untuk mengubah kode / data, makro pembaca digunakan sebelumnya ketika membaca teks untuk mengubah teks menjadi kode / data.
'something
adalah bentuk singkat untuk
(quote something)
`definisi sebenarnya yang digunakan bound-and-true-pjuga adalah pembaca makro. Jika mengutip simbol seperti di `symboldalamnya setara dengan 'symbol, tetapi ketika digunakan untuk mengutip daftar seperti di `(foo bar ,baz)dalamnya berperilaku berbeda dalam bentuk yang diawali dengan ,dievaluasi.
`(constant ,variable)
setara dengan
(list (quote constant) variable))
Ini harus menjawab pertanyaan mengapa simbol-simbol yang tidak dikutip kadang-kadang dievaluasi (diganti dengan nilainya) dan terkadang tidak; makro dapat digunakan quoteuntuk mencegah simbol dievaluasi.
Tapi mengapa bound-and-true-pmakro sementara boundptidak? Kita harus dapat menentukan apakah simbol sewenang-wenang, yang tidak dikenal sampai waktu berjalan, terikat sebagai simbol. Ini tidak akan mungkin terjadi jika boundpargumen dikutip secara otomatis.
bound-and-true-pdigunakan untuk menentukan apakah variabel yang dikenal didefinisikan dan jika demikian gunakan nilainya. Ini berguna jika perpustakaan memiliki ketergantungan opsional pada perpustakaan pihak ketiga seperti pada:
(defun foo-get-value ()
(or (bound-and-true-p bar-value)
;; we have to calculate the value ourselves
(our own inefficient or otherwise undesirable variant)))
bound-and-true-pdapat didefinisikan sebagai fungsi dan memerlukan argumen untuk dikutip tetapi karena itu dimaksudkan untuk kasus-kasus di mana Anda tahu di muka variabel apa yang Anda pedulikan tentang makro yang digunakan untuk menyelamatkan Anda dari keharusan mengetik '.
setqmerupakan singkatanset quoted, dan awalnya adalah makro yang diperluas ke(set 'some-variable "less"). Secara umum, Elisp tidak terlalu konsisten tentang argumen yang dikutip vs yang tidak dikutip, tetapi fungsi apa pun (bukan makro) yang perlu berinteraksi dengan variabel alih-alih nilai akan mengambil argumennya yang dikutip (setqmenjadi pengecualian utama).