それを行うには2つの方法があります。
最初の単純なバリアントは、単一または非常に限られた数のケースでのみ必要であり、プレフィックスとして単一のシンボルのみを使用することに満足している場合に適しています(!
例の場合のように)。読み取りマクロを作成できます。具体的には、macro-character
このような演算子を加算の代わりに使用するように設定します。
(set-macro-character #\! (lambda (stream char)
(declare (ignore char))
(cons '+ (let ((next (read stream t nil t)))
(if (consp next) next
(list next)))))
CL-USER> !1
1
CL-USER> !(1 2)
3
もう1つの、より複雑で柔軟な方法は、マクロを定義することです。このマクロ内でカスタム変換を適用し、連結プレフィックスコードをインクルードプレフィックスに変換します。foo(bar)
このトリックは、通常のLispリーダーがとの両方を同じように読み取るという事実を使用していfoo (bar)
ます。つまり、それらを2つの要素に分割します。
このようなマクロの単純なバージョンは、次のようになります。
(defmacro with-prefix-syntax (&body body)
`(progn ,@(loop :for tail :on body :while body
:collect (if (and (not (atom (second tail)))
(fboundp (first tail)))
(prog1 (cons (first tail) (second tail)
(setf tail (rest tail)))
(first tail)))))
トップレベルのフォームのみを変換します。
CL-USER> (macroexpand-1 '(with-prefix-syntax
print(1)))
(PROGN (PRINT 1))
CL-USER> (macroexpand-1 '(with-prefix-syntax
1))
(PROGN 1)
CL-USER> (macroexpand-1 '(with-prefix-syntax
print(1)
2))
(PROGN (PRINT 1) 2)
ただし、下位レベルでは機能しません。
CL-USER> (macroexpand-1 '(with-prefix-syntax
print(1)
(+ print(2))))
(PROGN (PRINT 1) (+ PRINT (2)))
すべてのレイヤーを再帰的に変換するのはかなり簡単ですが(これは読者の練習問題として残されています:)