マクロ衛生の一部だけを作る方法
質問
lambda
という版のlambda-r
というバージョンは、return
を作成できます。例:
(+ ((lambda-r ()
(return 1)
2)) 5)
.
これは値6
を与えるでしょう。値が7になると予想されるかもしれませんが、それは2の前にLambda-Expressionから戻されたため6です。
私が探している変革の種類の例です。次のように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-expressionで表現することもできますが、明確さのために定義を使用しています。
上記のコードは実際に期待どおりに機能します。 問題は、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 - 私は今それを持っています:)
解決
あなたが望むものはsyntax-case
ではなくsyntax-rules
です。
R6RS定義いくつかの例、特に a構文オブジェクトとデータム変換のセクション。これはあなたが望むものです。loop
w / break
の例をreturn
に適応させることができるはずです。