Misalkan saya memiliki buffer Emacs lisp yang berisi:
(defvar foo 1)
Jika saya menelepon eval-last-sexp
atau eval-buffer
, foo
terikat ke 1. Jika saya mengedit buffer ini ke:
(defvar foo 2)
eval-last-sexp
dan eval-buffer
jangan mengeksekusi ulang baris ini, jadi foo
masih 1.
Ini sangat menantang ketika ada beberapa pernyataan seperti itu dan saya harus melacak garis mana yang tidak dievaluasi kembali.
Saya melihat hanya me-restart Emacs dan kemudian (require 'foo)
, tetapi kemudian saya harus berhati-hati untuk menghindari memuat file .elc yang lebih tua.
Bagaimana saya bisa benar-benar yakin bahwa variabel dan fungsi yang didefinisikan dalam file saat ini berada dalam keadaan yang sama seperti memuat kode baru dalam contoh Emacs baru?
interactive-development
Wilfred Hughes
sumber
sumber
makunbound
dan kemudian mengevaluasi kembali kode dalam buffer.(incf emacs-major-version)
saya dapat hidup dengan terjadi berulang kali. Saya tertarik untuk meretas kode dengan banyakdefvar
bentuk.Jawaban:
Seperti yang dijelaskan dalam jawaban lain, mengevaluasi
defvar
formulir menggunakaneval-last-sexp
tidak mereset nilai default.Sebaliknya, Anda dapat menggunakan
eval-defun
(terikatC-M-x
diemacs-lisp-mode
secara default), yang mengimplementasikan perilaku yang Anda inginkan sebagai pengecualian khusus:Jika Anda perlu mengevaluasi konten lengkap dari buffer, Anda dapat menulis fungsi yang berjalan di formulir tingkat atas secara bergantian dan memanggil
eval-defun
masing-masing. Sesuatu seperti ini seharusnya bekerja:sumber
eval-defun
sajaeval-last-sexp
. Anda bahkan dapat menulis fungsi yang memanggileval-defun
setiap formulir di buffer, dan menggunakannya sebagai gantinyaeval-buffer
.eval-defun
alih-aliheval-last-sexp
, tentu saja, tetapi kesulitannya adalah untukeval-buffer
.eval-defun
setiap formulir tingkat atas di buffer.defvar
tidak ada dalamdefun
. Contoh:(progn (defvar foo "bar"))
.defconst
(yang selalu dievaluasi ulang). Baru-baru ini ada posting yang sangat mencerahkan tentang topik ini dalam tanda kurung tanpa akhirSeperti jawaban yang lain katakan, ini hanya cara defvar bekerja, tetapi Anda dapat mengatasinya, ini adalah hal yang paling sulit.
Anda dapat mendefinisikan kembali sementara bagaimana defvar bekerja jika Anda ingin dan selama waktu itu, memuat ulang paket yang ingin Anda atur ulang.
Saya menulis makro di mana selama evaluasi tubuh, nilai-nilai defvars akan selalu dievaluasi kembali.
Contoh penggunaan:
file_a.el
file_b.el
Catatan: Ini hanya digunakan untuk tujuan mengevaluasi kembali defvars, karena hanya mengabaikan dokumen ketika mengevaluasi ulang. Anda dapat memodifikasi makro untuk mendukung evaluasi ulang yang menerapkan dokumen juga, tapi saya akan menyerahkannya kepada Anda.
Dalam kasus Anda, Anda bisa melakukannya
Tapi ketahuilah apa yang dilakukan oleh elisp agar mengharapkan defvar berfungsi seperti yang ditentukan, bisa jadi mereka menggunakan defvar untuk mendefinisikan dan setq dalam beberapa fungsi init untuk menentukan nilainya, sehingga Anda bisa berakhir dengan nil'ing variabel yang tidak Anda inginkan tetapi ini mungkin jarang terjadi.
Implementasi Alternatif
Dengan menggunakan ini, Anda bisa mendefinisikan ulang defvar secara global dan mengontrol apakah itu akan menetapkan nilai simbol ke argumen INIT-VALUE bahkan jika simbol tersebut didefinisikan dengan mengubah nilai
defvar-always-reeval-values
simbol baru .sumber
defvar
adalah ide yang baik: ada beberapa kemungkinan penggunaandefvar
, dengan semantik yang sedikit berbeda. Sebagai contoh, salah satu penggunaan makro Anda tidak memperhitungkan adalah(defvar SYMBOL)
formulir, yang digunakan untuk memberitahu byte-compiler tentang keberadaan variabel tanpa menetapkan nilai.defvar
dengan makro, Anda mungkin akan lebih baik mengawalidefvar
bentuk asli denganmakunbound
, daripada menggantinya dengansetq
.The
defvar
sedang dievaluasi dan melakukan apa yang telah Anda tentukan. Namun,defvar
hanya menetapkan nilai awal:Jadi untuk mencapai apa yang Anda inginkan, Anda harus melepaskan ikatan variabel sebelum mengevaluasi ulang, mis
atau gunakan
setq
untuk mengatur nilai, misJika Anda tidak perlu menentukan docstring di sini, Anda dapat melewati
defvar
semuanya.Jika Anda benar-benar ingin menggunakan
defvar
dan melepaskan ikatan ini secara otomatis, Anda harus menulis fungsi untuk menemukandefvar
panggilan di buffer saat ini (atau wilayah, atau sexp terakhir, dll); panggilanmakunbound
untuk masing-masing; dan kemudian melakukan eval yang sebenarnya.sumber
eval-buffer
pembungkus yang akan melepaskan ikatan segalanya terlebih dahulu, tetapi jawaban @ Francesco tentangeval-defun
benar-benar apa yang Anda inginkan.Makro berikut dibuat dengan menelusuri
eval-defun
fungsi pendukungnya dan memodifikasinya sehingga tidak perlu lagi mengevaluasi wilayah buffer tertentu. Saya membutuhkan bantuan di utas terkait. Mengubah ekspresi menjadi string , dan @Tobias datang untuk menyelamatkan - mengajari saya cara mengubah fungsi tidak sempurna menjadi makro. Saya tidak berpikir kita haruseval-sexp-add-defvars
mendahuluielisp--eval-defun-1
, tetapi jika seseorang berpikir itu penting, beri tahu saya.sumber
Masalahnya bukan bahwa garis tidak dievaluasi kembali. Masalahnya adalah bahwa
defvar
mendefinisikan suatu variabel dan nilai defaultnya . Jika variabel sudah ada, maka mengubah nilai defaultnya tidak mengubah nilai saat ini. Sayangnya, saya pikir Anda perlu menjalankansetq
untuk setiap variabel yang nilainya ingin Anda perbarui.Ini mungkin berlebihan, tetapi Anda dapat memperbarui file seperti ini jika Anda ingin dapat dengan mudah memperbarui
foo
ke nilai default yang baru.tetapi itu mengharuskan Anda mempertahankan nilai default di dua tempat dalam kode Anda. Anda juga bisa melakukan ini:
tetapi jika ada kesempatan yang
foo
dinyatakan di tempat lain Anda mungkin memiliki beberapa efek samping untuk dihadapi.sumber
eval-defun
memperlakukandefvar
secara khusus, jadi pasti ada sesuatu yang serupa untuk seluruh penyangga?makunbound
dideklarasikan oleh variabel apa pun di buffer saat ini, dan kemudian evaluasi ulang? Anda dapat menulis sendiri, tetapi saya tidak berpikir bahwa ada fungsi out-of-the-box untuk ini. EDIT: Sudahlah, saya mengerti apa yang Anda katakan. Sebuaheval-defun
yang berfungsi pada seluruh buffer. Sepertinya @JordonBiondo punya solusi untuk itu.defvar
tidak melakukan apa-apa jika variabel sudah memiliki nilai (seperti yang dikatakan oleh dok:)The optional argument INITVALUE is evaluated, and used to set SYMBOL, only if SYMBOL's value is void.
. Masalahnya bukan yangdefvar
mengubah nilai default dan bukan nilai saat ini.(defvar a 4) (default-value 'a) (setq a 2) (default-value 'a)
; kemudianC-x C-e
setelahdefvar
sexp; kemudian(default-value 'a)
.C-x C-e
,,eval-region
dan sejenisnya padadefvar
sexp tidak mengubah nilai default.