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