Поддержка 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, которые вы перечислили, но он должен работать, если они соответствуют стандартам.

Другие вопросы по тегам