Kapan kutipan tajam digunakan?

10

Saya melihat kutipan tajam digunakan dalam kode eLisp orang lain, dan saya menggunakannya sendiri, tetapi saya tidak sepenuhnya jelas kapan mereka sesuai dan kapan tidak.

Adakah yang bisa mengklarifikasi kapan tepatnya tepat menggunakan kutipan tajam dan kapan kutipan tunggal biasa digunakan?

izkon
sumber
3
nb Ada banyak duplikat untuk pertanyaan ini di sini atau di SO
phils
Kemungkinan rangkap dari Kapan harus mengutip dengan tajam ekspresi lambda?
Andrew Swann
1
Saya tidak berpikir itu adalah duplikat: emacs.stackexchange.com/questions/3595 adalah tentang menggunakan #'lambda (di mana jawabannya pada dasarnya "tidak pernah"), sedangkan pertanyaan @ izkon berlaku bukan pada penggunaan #'simbol yang diterapkan.
Stefan

Jawaban:

12

#'hanya singkatan untuk function, sama seperti 'singkatan untuk quote.

Anda dapat menggunakannya di mana saja di mana Anda ingin menunjukkan ke byte-compiler atau interpreter atau pembaca manusia bahwa argumennya diharapkan (diperlakukan sebagai) fungsi.

Dalam banyak konteks, konteks menentukan bagaimana argumen diperlakukan jika, misalnya, Anda cukup mengutipnya (menggunakan quoteatau ') alih-alih menggunakan #'(atau function). Misalnya, dalam konteks di mana simbol hanya digunakan untuk symbol-functionpropertinya, yaitu, ia digunakan sebagai fungsi, Anda bisa meneruskan simbol (misalnya dengan mengutip atau melewati variabel yang nilainya adalah simbol).

Namun terkadang kode lebih jelas jika Anda menggunakannya #'dalam konteks seperti itu. Bahkan jika Emacs-Lisp sendiri memahami bahwa simbol digunakan sebagai fungsi dalam konteks seperti itu, mungkin membantu untuk menekankan ini untuk pembaca kode manusia.

Dalam beberapa Lisps lain, perlakuan bentuk lambda yang hanya dikutip (dengan ') atau tidak dikutip dapat berbeda dari penggunaannya dalam posisi fungsi ketika dikutip menggunakan function( #'). Tetapi tidak di Emacs Lisp. Di Emacs Lisp Anda tidak perlu mengutip (menggunakan salah satu 'atau #') formulir lambda yang ingin Anda perlakukan sebagai fungsi (dan bukan hanya sebagai daftar). Jika Anda ingin itu ditangani hanya sebagai daftar, dengan mobil lambdadll, maka kutiplah (dengan ') - contoh di bawah ini menggambarkan hal ini.

Dari (elisp) Fungsi Anonim :

- Formulir Khusus: function function-object

Formulir khusus ini kembali FUNCTION-OBJECTtanpa mengevaluasinya.

Dalam hal ini, mirip dengan quote(* note Quoting: :). Tetapi tidak seperti quoteitu, ia juga berfungsi sebagai catatan untuk evaluator Emacs dan byte-compiler yang FUNCTION-OBJECTdimaksudkan untuk digunakan sebagai fungsi. Dengan asumsi FUNCTION-OBJECTadalah ekspresi lambda yang valid, ini memiliki dua efek:

• Ketika kode dikompilasi dengan byte, FUNCTION-OBJECTdikompilasi menjadi objek fungsi kode-byte (* note Kompilasi Byte: :).

• Ketika pengikatan leksikal diaktifkan, FUNCTION-OBJECTdiubah menjadi penutupan. * Catatan Penutupan ::.

Sintaks baca #'adalah kependekan dari penggunaan function. Formulir berikut semuanya setara:

(lambda (x) (* x x))
(function (lambda (x) (* x x)))
#'(lambda (x) (* x x))

Dalam contoh berikut, kami mendefinisikan change-propertyfungsi yang menggunakan fungsi sebagai argumen ketiga, diikuti oleh double-property fungsi yang memanfaatkannya change-propertydengan meneruskannya fungsi anonim:

(defun change-property (symbol prop function)
   (let ((value (get symbol prop)))
     (put symbol prop (funcall function value))))

(defun double-property (symbol prop)
   (change-property symbol prop (lambda (x) (* 2 x))))

Perhatikan bahwa kami tidak mengutip lambdaformulir.

Jika Anda mengkompilasi kode di atas, fungsi anonim juga dikompilasi. Ini tidak akan terjadi jika, katakanlah, Anda telah membangun fungsi anonim dengan mengutipnya sebagai daftar:

(defun double-property (symbol prop)
   (change-property symbol prop '(lambda (x) (* 2 x))))

Dalam hal itu, fungsi anonim disimpan sebagai ekspresi lambda dalam kode yang dikompilasi. Byte-compiler tidak dapat menganggap daftar ini sebagai suatu fungsi, walaupun ia terlihat seperti satu, karena ia tidak tahu yang change-propertybermaksud menggunakannya sebagai suatu fungsi.

Drew
sumber
9

#'(alias function) dapat digunakan di depan (lambda ...)tetapi itu berlebihan di sana, jadi satu-satunya tempat di mana itu benar-benar bermakna adalah di depan simbol, seperti di #'car. Dalam ELisp, #'cardan 'carhampir sepenuhnya sama, jadi salah satu tujuan utamanya adalah untuk mendokumentasikan niat (yaitu untuk menunjukkan kepada siapa pun yang membaca kode ini bahwa Anda bermaksud menggunakan simbol ini sebagai fungsi). Namun ada beberapa keadaan, di mana perbedaannya lebih signifikan:

  • Byte-compiler mengambil keuntungan dari niat yang didokumentasikan ini dan ketika Anda menulisnya #'carakan memeriksa apakah carada sebagai fungsi, dan jika tidak menemukannya, ia akan memancarkan peringatan, seperti halnya jika Anda memiliki panggilan ke fungsi tersebut .
  • Di dalam cl-fletdan cl-labels, hanya #'fbisa merujuk ke fungsi yang ditentukan secara lokal f, karena 'fmasih akan merujuk ke simbol global f(dan fungsi mana saja yang mungkin disimpan dalam symbol-functionslotnya). Misalnya

    (cl-flet ((car (x y) (+ x y)))
      (list #'car 'car))
    =>
    ((closure nil (x y) (+ x y)) car)
    
Stefan
sumber