マクロではなく関数に関する関連する質問のコメント スレッドに触発されました。
新しい定義で構文の以前の定義を使用できるように、Scheme 構文定義を拡張する方法はありますか? さらに、これは拡張可能である必要があります。つまり、技術を複数回連鎖させることが可能でなければなりません。
たとえば、でlambda
定義された関数が呼び出されるたびにlambda
、関数本体を実行する前に「foo」を出力するように拡張したいとします。これは次の方法で行うことができます。
(define-syntax old-lambda lambda)
(define-syntax lambda
(syntax-rules ()
((_ args body ...)
(old-lambda args (display "foo") body ...))))
次のようにして、これを別の方法で拡張することもできます (たとえば、「バー」を印刷することによって)。
(define-syntax old-lambda-2 lambda)
(define-syntax lambda
(syntax-rules ()
((_ args body ...)
(old-lambda-2 args (display "bar") body ...))))
最終的に、 new で定義された関数lambda
は、呼び出されるたびに「foo」、次に「bar」を出力します。
ただし、名前空間を大量の で汚染するだけでなく、これを行うたびにソース コード レベルでold-lambda-<x>
新しいものを作成する必要があります。たとえば、構文定義でもold-lambda-<x>
使用できないため、これを自動化することはできません。gensym
したがって、これを拡張可能にする良い方法はありません。唯一のもっともらしい解決策は、それぞれに名前を付けるold-lambda-print-foo
か、あいまいさを解消するのに似たものにすることですが、これは明らかに確実な解決策ではありません。(これがどのように失敗するかの例として、コードの2つの異なる部分がlambda
「foo」を出力するように拡張されたとします。当然、両方とも名前が付けられold-lambda-print-foo
、voila!lambda
は無限ループになります。)したがって、非常に理想的には次のような方法でこれを行うことができれば素晴らしいです。
- 多くの名前空間を汚染する必要はありません
old-lambda-<x>
- または、それが失敗すると、衝突が発生しないことが保証されます。