Как сделать часть макроса гигиеничной

Я хотел бы иметь версию lambda под названием lambda-r, из которой можно return. Пример:

(+ ((lambda-r ()
    (return 1)
    2)) 5)

Это даст значение 6. Хотя вы могли бы ожидать, что значение будет равно 7, оно равно 6, поскольку 1 возвращается из лямбда-выражения до того, как будет достигнуто значение 2.

Вот пример трансформации, которую я ищу. Допустим, кто-то должен был использовать lambda-r следующим образом:

(lambda-r (a b)
    (return a)
    (+ a b))

Я хочу, чтобы он был преобразован следующим образом:

(call/cc (lambda (k)
       (define return (lambda (v)
                        (k (lambda (a b)
                             v))))
       (lambda (a b)
         (return a)
         (+ a b))))

Это также можно было бы выразить с помощью выражения let вместо внутреннего определения, но я использую определение для ясности.

Обратите внимание, что приведенный выше код действительно работает так, как ожидалось. Проблема заключается в том, что мне не удается представить lambda-r в виде макроса. Причина в том, что я хочу, чтобы k и v были гигиеничными, но я не хочу, чтобы return был гигиеничным.

Мой макрос на данный момент таков:

(define-syntax lambda-r
  (syntax-rules (return)
    [(_ (var ...) body ...)
     (call/cc (lambda (k)
           (define return (lambda (v)
                            (k (lambda (var ...)
                                 v))))
           (lambda (var ...)
             body ...)))
     ]))

Что не работает, потому что return обрабатывается гигиенически и в результате не виден напрямую при использовании lambda-r. Таким образом, (lambda-r () (return 1)) выдает ошибку, говорящую о том, что return не является допустимым идентификатором.


Редактировать: благодаря ответу Натана Сандерса я ближе к пониманию того, что я должен здесь делать. Однако я не полностью понимаю следующие процедуры, и в результате еще не смог заставить это работать. Я был бы очень признателен, если бы вы могли объяснить/направить меня к ресурсам, которые объясняют следующее:

  • процедура syntax
  • процедуры datum->syntax/syntax->datum

Редактировать: Nevermind - теперь у меня есть :)


person Cam    schedule 10.07.2010    source источник


Ответы (1)


Вам нужно syntax-case вместо syntax-rules.

Определение R6RS содержит несколько примеров , в частности раздел о синтаксисе -преобразование объектов и данных, что вам и нужно. Вы должны быть в состоянии адаптировать пример loop с break к вашему return.

person Nathan Shively-Sanders    schedule 10.07.2010
comment
Спасибо, я думаю, это то, что я ищу. Я читал эту страницу, и это немного сложно переварить; Вы можете объяснить, что делает процедура syntax? Также было бы полезно более простое для понимания описание with-syntax и datum->syntax/syntax->datum. - person Cam; 11.07.2010
comment
Я больше не могу редактировать этот комментарий, но он все еще меня раздражает: *теперь я понимаю эти термины :) - person Cam; 12.07.2010