Больше макросов - PullRequest
       0

Больше макросов

0 голосов
/ 28 сентября 2018

У меня все еще есть некоторые проблемы с этой концепцией.Ключевой параграф в стандарте 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.Но как насчет внутренних ссылок на эту лямбду, мы должны также изменить их?Это кажется очевидным, но не было явно указано в стандарте.

Также я до сих пор не уверен, лучше ли иметь отдельную фазу расширения, отдельную от компилятора, или переплетать расширяющиеся макросы с компиляцией кода.

Спасибо, и извините, если я что-то упустил, очевидно, относительно новый для этого.

Стив

Ответы [ 2 ]

0 голосов
/ 02 октября 2018

Спасибо, я думаю, я понимаю ... Я все еще удивляюсь, как при определенных обстоятельствах достигается гигиена, например.следующее:

(define (myproc x)
  (let-syntax ((double (syntax-rules ()
    ((double) (+ x x)))))
    ((lambda (x) (double)) 3)))

(myproc 42)

Сайт имеет 84, а не 6. Интересно, как эта (правильная) ссылочная прозрачность достигается просто переименованием.Выходной сигнал трансформатора не связывает новые переменные, но, тем не менее, когда он расширяется в строке 4, мы должны найти способ добраться до желаемого x, а не самого последнего.

Лучший способ, которым я могу думатьэто просто переименовывать каждый раз, когда лямбда-аргумент или определение затеняет другой, т.е.продолжайте добавлять %1, %2 и т. д. .... макро-выходам будут называться их точные версии (например, x%1), в то время как ссылки на идентификаторы просто имеют свое неукрашенное имя x, и во время компиляции будет найдена правильная переменная.

Спасибо, надеюсь на любые разъяснения.

Стив

0 голосов
/ 30 сентября 2018

В первом примере правильно написано:

(define x 42)

(define-syntax double
  (syntax-rules ()
    ( (_) ((lambda () (+ x x))) ) ))

(set! x 3)
(double)

единственная возможность - 6 , поскольку существует только одна переменная с именем x.

.второй пример, правильно написанный:

(define x 42)

(define-syntax double
  (syntax-rules ()
    ((_) ((lambda () (+ x x))) )))

(define (proc)
  (define x 3)
  (double))

(proc)

гигиеническая природа макросистемы Схемы предотвращает захват несвязанного локального x, поэтому результат равен 84 .

Как правило, идентификаторы (например, ваши x) в правилах синтаксиса относятся к тому, к чему они лексически относятся (глобальный x в вашем случае).И это обязательство будет сохранено из-за гигиены.Из-за гигиены вам не нужно беспокоиться о непреднамеренном захвате.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...