Как сделать только часть макроса гигиенической
Я хотел бы иметь версию 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 - у меня есть это сейчас:)
1 ответ
Что вы хотите syntax-case
вместо syntax-rules
,
Определение R6RS дает несколько примеров, в частности, раздел о преобразованиях синтаксических объектов и базовых данных, что вам и нужно. Вы должны быть в состоянии адаптировать loop
ж / break
пример для вашего return
,