Simbol yang berada di posisi non-fungsi diperlakukan sebagai nama variabel. In (function variable)
function
adalah dalam fungsi-posisi (setelah tanda kurung buka) dan variable
tidak. 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-variable
terikat sebagai variabel" dan bukan "adalah simbol yang my-variable
terikat sebagai variabel.
Jadi mengapa bound-and-truep
berperilaku 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-p
tampilannya:
(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 nil
jika my-variable
tidak boundp
atau 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. quote
adalah 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 quote
untuk 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-p
juga adalah pembaca makro. Jika mengutip simbol seperti di `symbol
dalamnya 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 quote
untuk mencegah simbol dievaluasi.
Tapi mengapa bound-and-true-p
makro sementara boundp
tidak? Kita harus dapat menentukan apakah simbol sewenang-wenang, yang tidak dikenal sampai waktu berjalan, terikat sebagai simbol. Ini tidak akan mungkin terjadi jika boundp
argumen dikutip secara otomatis.
bound-and-true-p
digunakan 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-p
dapat 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 '
.
setq
merupakan 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 (setq
menjadi pengecualian utama).