Önemli bir tuzak, tanımlanmamış değişkenler için bağlanma semantiğinin - yani tanımlanmamış değişkenlerin defvar
ve arkadaşların - şununla değişmesidir lexical-binding
: Onsuz, let
her şeyi dinamik olarak bağlar, ancak lexical-binding
tanımlanmamış değişkenlerle birlikte sözlü olarak bağlanır ve hatta mevcut sözcüksel kapsamda kullanılmazsa tamamen ortadan kaldırılır .
Eski kod bazen buna dayanır. Opsiyonel özellikler için sabit bağımlılıkları önlemek için, dinamik değişkenleri bağlamak istiyorum olmadan gelen kütüphane gerektiren veya değişken kendisini bildirerek:
(let ((cook-eggs-enabled t))
(cook-my-meal))
Pişirme özelliği isteğe bağlıysa, kullanıcıya gereksiz bağımlılıkları zorlamak istemiyoruz, bu nedenle işlevin (require 'cook)
otomatik yüklenmesini kullanmıyoruz cook-my-meal
.
cook-eggs-enabled
Yerel bir değişken olmayan insan okuyucu için açıktır , ancak yine de buradaki cook
kütüphaneden bazı küresel dinamik değişkenlere atıfta bulunmaktadır . lexical-binding
Bu kod olmadan amaçlandığı gibi çalışır: cook-eggs-enabled
tanımlanmış olsun ya da olmasın dinamik olarak bağlıdır.
İle lexical-binding
: ancak, kırılır cook-eggs-enabled
şimdi bağlandığı lexically (Bu kullanılmaz çünkü, uzak ve daha sonra optimize edilmiş) küresel dinamik değişken yüzden cook-eggs-enabled
edilir değil şimdiye hala hiç dokundu ve nil
zaman cook-my-meal
denir şaşırtıcı bir herhangi yumurta olmaz bu yüzden, bizim yemek.
Neyse ki, bu konuların tespit edilmesi çok kolaydır : Bayt derleyici doğal olarak burada kullanılmayan sözlük bağlaması konusunda uyarır .
Düzeltme basittir: Ya (require 'cook)
(gerçekten isteğe bağlı olmayan özellikler için) ekleyin ya da - zor bağımlılıkları önlemek için değişkeni kendi kodunuzda dinamik değişken olarak bildirin . Bunun için özel bir defvar
form var:
(defvar cook-eggs-enabled)
Bu cook-eggs-enabled
dinamik değişken olarak tanımlanır , ancak değişkenin bağlayıcı niteliği dışında doktora, load-history
(ve dolayısıyla find-variable
ve arkadaşların) veya başka herhangi bir şeyi etkilemez .
cook-eggs-enabled
olmaya bağlanmamış zamanlet
bitirir? Eminim daha önce böyle bir hatayla karşılaştım. Defvar, içinde gerçekleşiyordulet
velet
daha sonra değişkeni ilk (geçersiz) durumuna geri yükledi.