Apakah mungkin untuk melampirkan string dokumen yang dihasilkan ke lambda?

10

Emacs docs mengatakan bahwa ketika string doc dimasukkan ke dalam lambdaatau defun"disimpan langsung di objek fungsi". Namun, kita dapat mengubah dokumen dari fungsi-fungsi bernama seperti ini:

(put 'my-function-name 'function-documentation "Blah.")

Tetapi trik yang sama tidak bekerja dengan lambdas. Apakah ada cara untuk menambahkan dokumentasi ke lambda? Atau entah bagaimana secara dinamis menghasilkan doc-string literal?

Untuk memperjelas, bayangkan situasi berikut:

(let ((foo 1)
      (bar 2))
  (lambda ()
    (+ foo bar)))

Saya ingin lambda memiliki string doc yang menyebutkan nilai foodan bar.

Mark Karpov
sumber

Jawaban:

12

Yah lambdas dapat memiliki dokumen biasa seperti halnya definisi fungsi lainnya:

(lambda ()
   "I'm a docstring!"
   (+ foo bar))

Jadi Anda bisa menggunakan:

(let ((foo 1)
      (bar 2))
  `(lambda ()
     ,(format "Function which sums foo=%s and bar=%s" foo bar)
     (+ foo bar)))

Mengapa Anda menginginkan docstring pada fungsi anonim adalah pertanyaan lain, yang mungkin memengaruhi pendekatan yang Anda ambil.

Sebagai contoh jika Anda berencana untuk mengikatnya ke kunci dan Anda ingin C-h kmenampilkan bantuan itu, Anda bisa menggunakan pendekatan ini, tetapi tentu saja bantuan itu juga akan tetap menampilkan objek fungsi itu sendiri (termasuk docstring), yang tidak begitu Bagus; namun Anda bisa melakukan ini dan Anda akan (juga) melihat versi baik-diformat:

(global-set-key
 (kbd "C-c a")
 (let ((foo 1)
       (bar 2))
   `(lambda ()
      ,(format "Function which sums foo=%s and bar=%s" foo bar)
      (interactive)
      (+ foo bar))))

Anda mungkin lebih suka menggunakan simbol. Anda dapat memasangkan fungsi anonim dengan simbol yang tidak diinginkan , dan tidak khawatir tentang hal itu bertentangan dengan simbol lain dengan nama yang sama. Ini membuat pembersih bantuan, karena akan menampilkan nama simbol daripada objek fungsi. Dalam hal ini kita memiliki opsi untuk meneruskan docstring defaliasdaripada menanamkannya dalam bentuk lambda.

(global-set-key
 (kbd "C-c a")
 (let ((foo 1)
       (bar 2))
   (defalias (make-symbol "a-foo-bar-function")
     (lambda ()
       (interactive)
       (+ foo bar))
     (format "Function which sums foo=%s and bar=%s" foo bar))))

atau (dan ini adalah hal yang hampir sama) Anda dapat menangkap simbol yang tidak diinginkan, dan mengatur properti simbol secara langsung, sesuai kode asli Anda:

(global-set-key
 (kbd "C-c a")
 (let ((foo 1)
       (bar 2)
       (sym (make-symbol "a-foo-bar-function")))
   (put sym 'function-documentation
        (format "Function which sums foo=%s and bar=%s" foo bar))
   (defalias sym
     (lambda ()
       (interactive)
       (+ foo bar)))))

Sebagai catatan tambahan, ketahuilah bahwa fungsi ini hanya akan menjumlahkan nilai-nilai let-bound untuk foodan barjika Anda menggunakan lexical-binding: tuntuk pustaka Anda. Jika foo dan bar terikat secara dinamis, dokumen yang saya buat kemungkinan besar tidak akan akurat pada saat run-time. Kita sebenarnya bisa memenuhi situasi itu dengan dokumen dinamis . Node info (elisp) Accessing Documentationmengatakan tentang documentation-property:

Jika nilai properti bukan 'nihil', bukan string, dan tidak merujuk ke teks dalam file, maka nilai itu dievaluasi sebagai ekspresi Lisp untuk mendapatkan string.

Jadi dengan salah satu pendekatan berbasis simbol, kita dapat mengutip formulir dokumentasi untuk dievaluasi pada waktu panggilan:

(defalias (make-symbol "a-foo-bar-function")
   (lambda ()
     (interactive)
     (+ foo bar))
   '(format "Function which sums foo=%s and bar=%s" foo bar))
phils
sumber
13

Di Emacs-25, ada fitur baru persis untuk tujuan itu:

(let ((foo 1)
      (bar 2))
  (lambda ()
    (:documentation (format "Return the sum of %d and %d." foo bar))
    (+ foo bar)))
Stefan
sumber