Ошибка при расширении макроса в Chicken Scheme

Я изучаю, как работает система макросов в Scheme, и пытаюсь сделать мой код более похожим на JavaScript. Поэтому я подумал, что начну с function макро. Вот как я хочу, чтобы определение функции выглядело так:

(function id (x) x)

Следует расширить до следующего:

(define (id x) x)

Поэтому я пишу макрос следующим образом:

(define-syntax function
    (lambda (name args . body)
        `(define (,name ,@args) ,@body)))

Однако, когда я использую его, я получаю следующую ошибку (в Chicken Scheme):

Error: during expansion of (define ...) - in `define' - lambda-list expected: (define ((function id (x) x) . #<procedure (rename sym1348)>) #<procedure (compare s11400 s21401)>)

    Call history:

    <syntax>      (function id (x) x)
    <eval>    (##sys#cons (##core#quote define) (##sys#cons (##sys#cons name args) body))
    <eval>    (##sys#cons (##sys#cons name args) body)
    <eval>    (##sys#cons name args)    <--

Куда я иду не так? Кроме того, как мне прочитать такие сообщения об ошибках, чтобы можно было отлаживать программу самостоятельно?

2 ответа

Решение

В Схеме, используя синтаксические правила ():

(define-syntax function
  (syntax-rules ()
    ((function name (args ...) body ...)
     (define (name args ...) body ...))))

Ошибка, которую вы видите, заключается в том, что, по-видимому, компилятор Chicken Scheme ожидает вторую форму define-syntax чтобы быть процедурой расширения макроса - им обычно требуются аргументы для переименования и сравнения идентификаторов. lambda в вашем макросе не выдает подходящую функцию - syntax-rules делает.

Вышеуказанное гарантировано гигиеническое.

То, как вы определили макрос, неверно согласно документации Chicken. Ваш код, кажется, больше вдохновлен макросами Common Lisp. Проверьте документ здесь для define-syntax с функцией трансформатора:

Макрос должен быть определен как:

(define-syntax function
    (lambda (expr inject compare)
        `(define (,(cadr expr) ,@(caddr expr)) ,(cadddr expr))))

expr - это целое выражение макроса, т.е. (function id (x) x) и инжектировать и сравнивать - это специальные служебные функции, передаваемые макросу при выполнении раскрывающегося макроса.

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