Bir tampon için sözcük bağlamayı mümkün kılmanın potansiyel tuzakları nelerdir?


12

Bu, bu sorudaki sözcüksel bağlanma ile sözcüksel-let arasındaki tartışmadan esinlenmiştir . As sözcük bağlayıcı size yararlı kapanışları insanlar olanağı verir sen hep etkinleştirmediğinden neden JavaScript gibi diğer dillerde kullanılabilir?

Eski Emacsen ile geriye dönük uyumluluk olduğunu varsaymak, eski kod arabelleklerinde etkinleştirilirse hangi tuzakları aramanız gerektiğiyle ilgili bir endişe değil mi?

Yanıtlar:


13

Ö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 .


Dinamik durumda, kod parçacığı neden olmaz cook-eggs-enabledolmaya bağlanmamış zaman letbitirir? Eminim daha önce böyle bir hatayla karşılaştım. Defvar, içinde gerçekleşiyordu letve letdaha sonra değişkeni ilk (geçersiz) durumuna geri yükledi.
Malabarba

1
@Malababa Hayır, bu farklı bir durum. Nedeni için Değişkenleri Tanımlama'nın son paragrafına bakın .
lunaryorn
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.