Comment la portée des variables pour les macros est-elle déterminée?

11

Prenez l'exemple de macro suivant, défini dans macro.el.

(defmacro some-macro (&rest body)
  `(let ((some-variable 1))
     ,@body))

Et prendre la fonction suivante, définie dans un autre fichier , function.el.

(defun some-function ()
  (some-macro (do-something)))

Quand function.elest compilé en octets, sera-t- some-variableil lié sous une liaison lexicale ou dynamique?

Je comprends que cela dépend de l'utilisation du fichier -*- lexical-binding: t; -*-, donc ma question concerne spécifiquement les situations suivantes:

  1. Si function.elutilise une liaison lexicale, mais macro.elpas.
  2. Si macro.elutilise une liaison lexicale, mais function.elpas.

Cela fait-il une différence s'il some-vara été déclaré global (avec un defvar) à l'intérieur function.el? Si c'est le cas, je suis particulièrement intéressé par le cas où ce n'est pas le cas .

Malabarba
la source
Je pense que Jisang Yoo a couvert cela en détail à yoo2080.wordpress.com/2013/08/14/…
phils
Je ne sais pas avec certitude, mais je parierais que l'expansion de macro hérite de la sémantique de liaison du site d'expansion, pas de la définition de macro. Cela aurait du sens puisque l'expansion est en fait substituée sur le site d'appel. Mais: Pourquoi voulez-vous savoir? Avez-vous l'intention d'écrire du code qui repose réellement sur ces détails?!
lunaryorn
@lunaryorn la macro ne repose pas entièrement sur cela, mais elle peut produire des bugs surprenants pour l'utilisateur si elle ne respecte pas la liaison du fichier dans
lequel
@Malabarba Écrivez alors votre macro d'une manière qui ne dépend pas de la liaison dans le tampon cible. Ou encore mieux, n'utilisez pas du tout de macro.
lunaryorn
@lunaryorn Je n'étais pas tout à fait clair. La macro est juste une forme let, et elle fonctionne comme annoncé dans les deux cas. Je veux juste m'assurer que ce formulaire let suit la portée spécifiée dans le fichier dans lequel il est développé. Cette question fait partie de savoir si cela se produit automatiquement ou si j'ai besoin de coder cela dans la macro.
Malabarba

Réponses:

9

Le type de portée actif pour le (let ((some-variable ..)) ...)dans votre exemple est celui qui est actif sur le site de l'appel de macro (c'est-à-dire celui qui s'applique some-function).

Une macro peut savoir quel type de portée sera utilisé pour le code qu'elle renvoie en vérifiant la valeur de la lexical-bindingvariable.

Stefan
la source