eval-when-compile: defsubst vs defmacro vs define-inline

8

Saya mendefinisikan beberapa fungsi sederhana di init.el, misalnya my-cache-file:

(defconst my-cache-directory
  (expand-file-name ".cache" user-emacs-directory)) ; ~/.emacs/.cache

(defun my-cache-file (x)
  (expand-file-name x my-cache-directory))          ; ~/.emacs/.cache/x

(setq savehist-file
      (my-cache-file "savehist"))

(setq backup-directory-alist
      `(("." . ,(my-cache-file "backups/"))))

Ini sepertinya kasus penggunaan yang bagus untuk defsubst:

(defsubst my-cache-file (x) ...)

Kemudian saya mulai belajar tentang kompilasi, dan ingin lebih mengoptimalkan. Dengan naif saya mencoba:

(defsubst my-cache-file (x)
  (eval-when-compile (expand-file-name x my-cache-directory)))

tetapi kompiler mengeluh (benar) tentang variabel bebas x, jadi alih-alih saya membungkus kode panggilan:

(setq savehist-file
      (eval-when-compile (my-cache-file "savehist")))

(setq backup-directory-alist
      `(("." . ,((eval-when-compile (my-cache-file "backups/"))))

Penelepon terakhir itu mungkin harus mengevaluasi seluruh daftar pada saat kompilasi, jadi saya menarik eval-when-compile:

(setq backup-directory-alist
      (eval-when-compile `(("." . ,(my-cache-file "backups/")))))

Saya ingin menghindari membuang sampah sembarangan kode saya dengan lebih banyak eval-when-compilepanggilan dari yang diperlukan, dan saya ingin tahu apakah ada pendekatan yang lebih baik yang bisa saya ambil dengan menggunakan makro atau define-inline. The dokumentasi merek define-inlinesuara menjanjikan:

Fungsi yang didefinisikan melalui define-inline memiliki beberapa keunggulan sehubungan dengan makro yang didefinisikan oleh defsubst atau defmacro:

  • Mereka dapat diteruskan ke mapcar (lihat Fungsi Pemetaan).
  • Mereka lebih efisien.
  • Mereka dapat digunakan sebagai formulir tempat untuk menyimpan nilai-nilai (lihat Variabel yang Disamaratakan).
  • Mereka berperilaku dalam cara yang lebih dapat diprediksi daripada cl-defsubst (lihat Daftar Argumen dalam Ekstensi Lisp Umum untuk GNU Emacs Lisp).

Tapi sintaksnya terlihat rumit, dan saya tidak dapat menemukan satu contoh pun yang digunakan di alam liar. Saya juga tidak dapat menemukan penjelasan tentang klaimnya bahwa defsubst kurang efisien.

Adakah yang pernah menggunakan define-inline, atau ada makro berbeda yang harus saya perhatikan, atau haruskah saya tetap bertahan defsubst?

ivan
sumber

Jawaban:

6

Saya akan mengatakan tetap dengan defun.

Jika Anda ingin mencoba define-inline, yang baru (bahkan belum memiliki string doc!), Silakan.

Tetapi pikirkan berapa banyak yang ingin atau perlu Anda sebaris. Jarang membutuhkannya, IMO (tentu saja bukan untuk hal-hal yang Anda tunjukkan di sini, tetapi mereka tidak diragukan lagi hanya untuk menjawab pertanyaan).

Saya pasti akan merekomendasikan untuk tidak menggunakan defsubst. Anda mungkin tidak membutuhkannya, dan itu hanya akan menghalangi. Mungkin ada kasus penggunaan pada tahun 1985, tapi saya tahu tidak ada tempat di mana itu berguna sekarang. define-inlinetampaknya merupakan upaya untuk mendapatkan manfaat defsubsttanpa kerugian.

Pertanyaan ini mungkin terutama berdasarkan pendapat. Jawaban ini hanya satu pendapat, dalam hal apa pun.

Drew
sumber
Jawaban yang bagus, terima kasih! Anda benar, saya memilih contoh sederhana sebagian besar demi kejelasan. Saya ingin mencoba defmacroatau define-inlinesolusi, jadi saya mungkin akan menusuk mereka. Alangkah baiknya telah eval-when-compilememasukkan ekspresi yang dihasilkan.
ivan