Önemli bir tuzak, tanımlanmamış değişkenler için bağlanma semantiğinin - yani tanımlanmamış değişkenlerin defvarve arkadaşların - şununla değişmesidir lexical-binding: Onsuz, lether şeyi dinamik olarak bağlar, ancak lexical-bindingtanı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-enabledYerel bir değişken olmayan insan okuyucu için açıktır , ancak yine de buradaki cookkütüphaneden bazı küresel dinamik değişkenlere atıfta bulunmaktadır . lexical-bindingBu kod olmadan amaçlandığı gibi çalışır: cook-eggs-enabledtanı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-enablededilir değil şimdiye hala hiç dokundu ve nilzaman cook-my-mealdenir ş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 defvarform var:
(defvar cook-eggs-enabled)
Bu cook-eggs-enableddinamik 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-variableve arkadaşların) veya başka herhangi bir şeyi etkilemez .
cook-eggs-enabledolmaya bağlanmamış zamanletbitirir? Eminim daha önce böyle bir hatayla karşılaştım. Defvar, içinde gerçekleşiyorduletveletdaha sonra değişkeni ilk (geçersiz) durumuna geri yükledi.