У меня все еще есть некоторые проблемы с этой концепцией.Ключевой параграф в стандарте r7rs:
"Идентификаторы, которые появляются в шаблоне, но не являются переменными шаблона, или идентификатор ellipsis
вставляются в выходные данные в качестве литеральных идентификаторов. Если литеральный идентификатор вставляется каксвободный идентификатор, то он относится к привязке этого идентификатора, в пределах которого появляется экземпляр синтаксических правил. Если литеральный идентификатор вставляется в качестве связанного идентификатора, то он фактически переименовывается, чтобы предотвратить непреднамеренный захват свободных идентификаторов. "
Под «связанным идентификатором» я прав, что это означает любой аргумент для lambda
, верхнего уровня define
или определения синтаксиса, т.е.define-syntax
, let-syntax
или let-rec-syntax
?(Я думаю, что я мог бы обработать внутренние define
s с помощью хитрости во время компиляции, преобразовав их в лямбды.)
Под «свободным идентификатором» подразумевается любой другой идентификатор, который предположительно определен заранее с «связанным идентификатором»"выражение?
Мне интересно, как будет выглядеть следующий код:
(define x 42)
(define-syntax double syntax-rules ()
((_) ((lambda () (+ x x)))))
(set! x 3)
(double)
Если результат будет 84 или 6?
Как насчет этого:
(define x 42)
(define-syntax double syntax-rules ()
((_) ((lambda () (+ x x)))))
(define (proc)
(define x 3)
(double))
(proc)
Правильно ли я предположить, что, поскольку define-syntax
происходит на верхнем уровне, все его свободные ссылки относятся к переменным верхнего уровня, которые могут существовать или не существовать на момент определения.Поэтому, чтобы избежать коллизий с локальными переменными в момент использования, мы должны переименовать выведенную свободную ссылку, скажем, добавить «%» к имени (и запретить пользователю создавать символы с% в них).Помимо дублирования ссылки на переменную верхнего уровня, на этот раз с добавленным%.
Если макрос определен в некоторой форме вложенной области видимости (с let-syntax
или let-rec-syntax
), это дажехитрее, если это относится к переменным области действия.Когда используется макрос, он должен расширить эти ссылки до их формы в точке определения макроса, а не в точке использования.Поэтому я предполагаю, что лучший способ - это естественное расширение и сканирование результата на lambda
с, если он найдет, переименовать его аргументы в точке определения, как предлагает r7rs.Но как насчет внутренних ссылок на эту лямбду, мы должны также изменить их?Это кажется очевидным, но не было явно указано в стандарте.
Также я до сих пор не уверен, лучше ли иметь отдельную фазу расширения, отдельную от компилятора, или переплетать расширяющиеся макросы с компиляцией кода.
Спасибо, и извините, если я что-то упустил, очевидно, относительно новый для этого.
Стив