Поддержка Racket R6RS: синтаксис-кейс
Эта простая программа R6RS:
#!r6rs
(import (rnrs base)
(rnrs syntax-case)
(rnrs io simple))
(define-syntax stest
(lambda (x)
(syntax-case x ()
((_ z) #'(z 0)))))
(stest display)
работает с Chez, Guile и Ypsilon, но не с Racket. Это дает мне это:
test.scm: 7: 3: lambda: несвязанный идентификатор в среде преобразователя;
кроме того, нет #% приложения синтаксического преобразователя привязан
У меня вопрос, это сломано для R6RS или я должен сделать что-то еще? Я тестирую с версией 6.12.
1 ответ
Реализация Racket R6 RS не является несовместимой в этом случае. В самом деле, во всяком случае, он более точно следует стандарту: ваша программа, как она написана, не заботится о фазах импорта. Проблема в том, что define-syntax
оценивает его правую часть во время раскрытия, как отмечено в разделе 11.2.2 Определения синтаксиса:
Связывает <ключевое слово> со значением <выражения>, которое должно вычисляться во время расширения макроса для преобразователя.
В отличие от других стандартов Схемы, R6 RS старается различать фазы, поскольку он допускает произвольное программирование во время компиляции (в то время как другие стандарты Схемы не допускают). Поэтому в разделе 7.1 "Библиотечная форма" указывается, как импортировать библиотеки на определенных этапах:
Каждый <спецификация импорта> указывает набор привязок, которые будут импортированы в библиотеку, уровни, на которых они должны быть доступны, и локальные имена, под которыми они должны быть известны. <Спецификация импорта> должна быть одной из следующих:
<import set> (for <import set> <import level> ...)
<Уровень импорта> является одним из следующих:
run expand (meta <level>)
где <уровень> представляет точный целочисленный объект.
Поэтому вам необходимо импортировать (rnrs base)
на обоих run
а также expand
фазы, и вам нужно импортировать (rnrs syntax-case)
на этапе расширения. Вы можете сделать это с помощью следующей программы:
#!r6rs
(import (for (rnrs base) run expand)
(for (rnrs syntax-case) expand)
(rnrs io simple))
(define-syntax stest
(lambda (x)
(syntax-case x ()
((_ z) #'(z 0)))))
(stest display)
Эта программа работает в Racket. Я не проверял, работает ли он также на других реализациях Scheme, которые вы перечислили, но он должен работать, если они соответствуют стандартам.