Un obstáculo importante es que la semántica de enlace para variables indefinidas , es decir, variables no definidas con defvary amigos, cambia con lexical-binding: Sin ella, lo letune todo dinámicamente, pero con las lexical-bindingvariables indefinidas habilitadas están unidas léxicamente , e incluso se eluyen completamente si no se usan en el ámbito léxico actual. .
El código antiguo a veces se basa en esto. Para evitar dependencias difíciles para las características opcionales, vincularía variables dinámicas sin requerir la biblioteca correspondiente o declarar la variable en sí:
(let ((cook-eggs-enabled t))
(cook-my-meal))
Si la función de cocción es opcional, no queremos forzar dependencias innecesarias en el usuario, por lo que no utilizamos (require 'cook)y en su lugar confiamos en la carga automática de la cook-my-mealfunción.
Es obvio para el lector humano que cook-eggs-enabledno es una variable local, pero aún se refiere a alguna variable dinámica global de la cookbiblioteca aquí. Sin lexical-bindingeste código funciona según lo previsto: cook-eggs-enabledestá vinculado dinámicamente, ya sea definido o no.
Con lexical-bindingobstante, se rompe: cook-eggs-enabledahora está obligado léxico (y luego optimizado de distancia, ya que no se usa), por lo que la variable dinámica mundial cook-eggs-enabledestá no siempre toca en absoluto y todavía nilen el momento en cook-my-mealque se llama, por lo que es sorprendente que no vamos a tener ningún huevo en nuestra comida
Afortunadamente, estos problemas son muy fáciles de detectar : el compilador de bytes advierte naturalmente sobre un enlace léxico no utilizado aquí.
La solución es simple: agregue un (require 'cook)(para características que no son realmente opcionales de todos modos) o, para evitar dependencias difíciles, declare la variable como variable dinámica en su propio código . Hay una defvarforma especial para esto:
(defvar cook-eggs-enabled)
Esto se define cook-eggs-enabledcomo variable dinámica, pero no afecta la cadena de documentación, load-history(y por lo tanto find-variabley amigos) ni nada más, excepto la naturaleza de enlace de la variable.
cook-eggs-enabledse desvincularía cuandoletfinalice? Estoy bastante seguro de que me he encontrado con un error como este antes. El defvar estaba ocurriendo dentro dellet, y elletposterior restableció la variable a su estado inicial (nulo).