Saya tidak begitu jelas tentang semua variasi variabel buffer-lokal, bahkan setelah membaca semua dokumen dan banyak posting di SX.
Berikut ringkasan pemahaman saya:
(defvar foo ..)
mendeklarasikan variabel dinamis untuk file. Tetapi variabelnya adalah (1) tidak dikenal ke file lain kecuali mereka menyertakan defvar
pernyataan juga, dan (2) variabelnya adalah global dalam cakupan, bukan buffer lokal.
(make-variable-buffer-local foo)
setelah di defvar
atas memberitahu kompiler dan semua orang bahwa variabel foo harus diperlakukan sebagai penyangga-lokal di mana pun diset, ketika diatur. Jadi pola ini adalah gaya yang baik untuk mendeklarasikan variabel buffer-local, meletakkan kedua pernyataan tersebut secara berurutan di dalam file.
(defvar xxx ...) ;declare xxx with global scope
(make-variable-buffer-local 'xxx) ;but now make it buffer-local everywhere
Untuk kenyamanan, (defvar-local xxx ...)
formulir dapat digunakan sebagai satu baris, sebagai ganti dari dua baris di atas:
(defvar-local xxx ...) ;make xxx buffer local everywhere
Setelah dinyatakan seperti di atas, variabel xxx dapat digunakan seperti variabel lain dalam pernyataan setq.
Jika saya hanya ingin memiliki satu instance dari variabel buffer-lokal yang sudah menjadi variabel dinamis global, saya akan menggunakan deklarasi berikut. Yang pertama mendeklarasikan variabel dinamis lingkup global, dan pernyataan kedua hanya membuat satu instance dari versi buffer-lokal dari variabel itu, dalam buffer saat ini:
(defvar xxx ...) ;declare xxx with global scope
(make-local-variable 'xxx) ;make xxx local in this buffer only
Sekarang untuk pertanyaan explict saya (semua pertanyaan di atas adalah pertanyaan implisit tentang apakah pemahaman saya benar).
Saat mengatur nilai variabel, saya bisa menggunakan setq
atau
setq-local
. Kapan sebaiknya setq-local
digunakan? Mengapa?
Apa yang terjadi jika saya menggunakan setq-local
vars buffer-lokal, atau vars non-buffer-lokal?
Apakah setq-local
diperlukan untuk defvar-local
variabel yang dideklarasikan?
Akankah setq-local
pada defvar
variabel yang dinyatakan normal mengubahnya menjadi variabel buffer-lokal? (Dengan kata lain, apakah setq-local
itu setara dengan (make-variable-local xxx)
deklarasi?
sumber
(setq-local VAR VALUE)
hanya singkatan untuk(set (make-local-variable VAR) VALUE)
, yang (dan masih) idiom umum.Jawaban:
Sebagian besar asumsi Anda dekat. Saya akan menyebutkan beberapa nanti. Tapi, pertama pertanyaan utamanya.
Bentuknya
setq-local
hanya kenyamanan, itu sama dengan melakukanmake-local-variable
diikuti olehsetq
. Jika Anda telah melakukan C-h f setq-localuntuk melihat dokumentasi dan mengklik ke sumbernya, Anda mungkin telah melihat ini. Begitulah cara saya memverifikasi kesan pertama saya. Kode sedikit tidak jelas karena mengoptimalkan hal-hal seperti fakta yangmake-local-variable
sebenarnya mengembalikan variabel itu sendiri. Menggunakansetq-local
adalah cara untuk menunjukkan lokalitas dalam beberapa kode, sehingga orang lain tahu kode tidak bisa bermain dengan nilai global variabel. Anda tidak perlu menggunakannya untuk mengakses variabel lokal. Variabel apa pun dapat dibuat sebagai buffer-lokal dan itu akan memengaruhi semua kode yang menyentuh variabel (kecuali jika keluar dari caranya untuk mendapatkan salinan global dengansetq-default
atau serupa).Itulah jawaban utama. Sekarang, ada beberapa hal di latar belakang Anda yang sedikit aneh. Karena Anda bertanya tentang itu, saya akan membahas beberapa hal.
Yang pertama adalah "tidak diketahui file lain". Ini tidak benar. Kode apa pun dapat merujuk variabel global apa pun (itu sebabnya mereka disebut "global") tanpa menyertakan
defvar
(dan C-h f defvarmengatakan demikian). Bahkan, seharusnya hanya ada satu maindefvar
(dengan nilai docstring dan default) untuk setiap variabel global. Adefvar
dengan hanya nama variabel dapat digunakan untuk menekan peringatan byte-compiler. Emacs hanya menggunakan nilai dari yang pertama dilihatnya - dan docstring dari yang terakhir. Jika ada beberapadefvar
s dengan nilai / docstring mereka dapat membingungkan orang yang membaca kode. Dan urutan memuat file akan jadi masalah.Beberapa variabel dimaksudkan untuk digunakan hanya sebagai buffer-lokal dan mereka adalah yang menggunakan
defvar-local
(atau dua bagiandefvar
/make-variable-buffer-local
yang merupakan kependekan, sebagian besar dalam kode lama sebelum formulir pendek ditambahkan). Ini membuatnya menjadi buffer-lokal di semua buffer. Untuk beberapa variabel, penggunaan utamanya bukan buffer-local, tetapi untuk beberapa alasan Anda mungkin ingin satu buffer memiliki nilai yang berbeda. Saat itulah Anda menggunakanmake-local-variable
, biasanya dalam beberapa kode pengaturan buffer hampir tidak pernah tepat setelahdefvar
.Dan sebagai hal yang umum, ada dua tujuan untuk
defvar
formulir. Salah satunya adalah memiliki beberapa dokumentasi, sehingga C-h vdapat digunakan oleh orang lain untuk mengetahui untuk apa variabel tersebut. Yang kedua adalah mendeklarasikan nilai "default", sehingga variabel selalu disetel. Deklarasi nilai default hanya mempengaruhi instance global (atau default) variabel, dan hanya digunakan jika instance itu belum disetel ke sesuatu. Itu berarti bahwa jika Andasetq
beberapa variabel dan kemudian memasukkan file dengandefvar
(misalnya melalui arequire
), defvar tidak akan mengubah nilai.¹ Lebih tepatnya,
defvar
tidak mengubah nilai variabel jika sudah diatur (itu memang mengatur docstring); ini dimaksudkan agar file init pengguna dapat melakukan(setq some-variable)
sebelum paket dimuat untuk mengganti nilai default paket.sumber
set-local
memberi tahu pembaca bahwa var lokal sedang diset. Apa pun yang dapat saya lakukan untuk meningkatkan keterbacaan kode saya adalah baik! PS. Saya akan mencoba mengklik ke sumber lebih sering; pada tingkat perkembangan saya saat ini, sering kali tidak benar-benar mencapai semantik ... :-)defvar
untuk setiap variabel global" tidak sepenuhnya benar - ada situasi ketika(defvar VARNAME)
tanpa nilai harus dinyatakan, terlepas dari definisi yang tepat (dengan nilai awal dan idealnya adalah sebuah dokumentasi) dari VARNAME itu.setq-local
dandefvar-local
hanya diperkenalkan di Emacs 24.3.(defvar varname)
harus dinyatakan tanpa nilai? Saya berpikir itulah yang disarankan Drew di utas lain ketika saya bertanya bagaimana cara menghilangkan peringatan variabel gratis di file saya untuk global yang telah saya nyatakan di tempat lain. Saya melakukannya sekarang. Apakah itu situasi yang Anda bicarakan?C-h i g (elisp) Warning Tips
). Yang lainnya adalah untuk perpustakaan yang menggunakan lexical-binding, untuk memastikan (jika perlu) bahwa suatu variabel terikat secara dinamis daripada terikat secara leksikal.