Comment rendre hygiénique une partie seulement d'une macro
Question
J'aimerais avoir une version de lambda
, appelé lambda-r
, à partir duquel vous pouvez return
.Un exemple:
(+ ((lambda-r ()
(return 1)
2)) 5)
Cela donnerait la valeur 6
.Bien que vous puissiez vous attendre à ce que la valeur soit 7, elle est 6 car 1 est renvoyé par l'expression lambda avant que 2 ne soit atteint.
Voici un exemple du type de transformation que je recherche.Disons que l'on utilise lambda-r
comme suit:
(lambda-r (a b)
(return a)
(+ a b))
Je veux qu'il soit transformé comme ceci :
(call/cc (lambda (k)
(define return (lambda (v)
(k (lambda (a b)
v))))
(lambda (a b)
(return a)
(+ a b))))
Cela pourrait également être exprimé avec une expression let au lieu d'une définition interne, mais j'utilise la définition par souci de clarté.
Notez que le code ci-dessus fonctionne réellement comme prévu. Le problème c'est que j'ai du mal à m'exprimer lambda-r
comme un macro.La raison est que je veux k
et v
pour être hygiénique, mais je ne veux pas return
pour être hygiénique.
Ma macro du moment est la suivante :
(define-syntax lambda-r
(syntax-rules (return)
[(_ (var ...) body ...)
(call/cc (lambda (k)
(define return (lambda (v)
(k (lambda (var ...)
v))))
(lambda (var ...)
body ...)))
]))
Ce qui ne marche pas parce que return
est traité de manière hygiénique et n'est donc pas directement visible lors de l'utilisation lambda-r
.Donc (lambda-r () (return 1))
donne une erreur qui dit que return
n'est pas un identifiant valide.
Modifier:Grâce à la réponse de Nathan Sanders, je comprends mieux ce que je dois faire ici.Cependant, je ne comprends pas entièrement les procédures suivantes et, par conséquent, je n'ai pas encore réussi à faire fonctionner cela.J'apprécierais vraiment que vous puissiez m'expliquer/me diriger vers des ressources qui expliquent ce qui suit :
- le
syntax
procédure - le
datum->syntax
/syntax->datum
procédures
Modifier:Peu importe, je l'ai maintenant :)
La solution
Ce que tu veux c'est syntax-case
au lieu de syntax-rules
.
La définition du R6RS donne quelques exemples, notamment une section sur les conversions syntaxe-objet et donnée, c'est ce que vous voulez.Vous devriez être capable d'adapter le loop
avec break
exemple à votre return
.