Common Lispの系譜を継ぐマイコン上のuLispをラズパイPico2上で練習中。今回はCommon LispとuLispの大きな違いの一つ、マクロについて調べてみます。Lispの中には、関数、マクロ、スペシャルフォームなどあり、その挙動が異なります。しかし、どうもuLispにはマクロはないみたい。
※Lispと一緒 投稿順 index はこちら
※実機確認は Raspberry Pi Pico2で行ってます。
※使用させていただいとります uLisp のバージョンは 4.6b (Arm用)です。
※uLispとCommon Lispとの動作比較のために使わせていただいている処理系は以下です。
SBCL 2.2.2 (SBCL = Steel Bank Common Lisp )
関数、マクロ、スペシャルフォーム
カッコで括られた( )の中に、最初に書いたお名前が、いつも関数名だと思うとさにあらず、以下の種別があり~の。
-
- 関数
- マクロ
- スペシャルフォーム(Special form)
上記のものどもの挙動の差については、Lisp素人のお惚け老人は詳しい思想を述べられませぬ。各種Lispの文献等をご参照くだされ。お惚け老人の理解では、関数に渡された引数共を先に評価してもらってから受け取る関数、とりあえずS式のまま受け取って、マクロの中の構造に埋め込んでから評価するマクロ、という感じっすかね。スペシャルフォームはその中間で如何ようにも自由に処理することが可能だと。ここでまず重要なのは、
-
- Lispの世界の中で、関数とマクロは自前定義できる(Common Lispでは。)
- スペシャルフォームは、Lispの世界の外、多分Cのソースをいじらんと新設不能。
ということであります。
しかし、uLispの場合、規模の小さなマイコンメモリに押し込むためなのか、
defmacro
という「マクロ」を欠いているようです。マクロを定義するためのマクロね。実際 defmacro と打ち込んでみたけどundefined とか言われて怒られました。
しかし、「よくつかう」ものどもの中にもマクロはいます。いつもお世話になっている、関数定義するときに使う defun とか、変数定義の defvar などもマクロですぜ(Common Lispでは。)
uLispの場合、Common Lispでマクロとして定義されているものどもの多くは
スペシャルフォーム
ということで実装しているみたいです。つまり新たな自前のマクロを定義するためのマクロは欠いているけれども、よく使うマクロどもには同名のスパシャルフォームがあると。さらにいうと、普通のスペシャルフォーム以外に、
Tail-recursive form
というお名前のスペシャルフォームの分家?もあるみたい。知らんけど。
uLispでの実装
以下は、Arm用の uLisp 4.6b でスペシャルフォーム、SP(およびTail-recursive form、TF)として実装されているものどもがCommon Lisp上でどう扱われているのかを列挙してみた表なんであります。作成には結構苦労したのよ。
name | Common Lisp | uLisp |
---|---|---|
progn | Special Form | TF |
if | Special Form | TF |
cond | Macro | TF |
when | Macro | TF |
unless | Macro | TF |
case | Macro | TF |
and | Macro | TF |
or | Macro | SP |
decf | Macro | SP |
defun | Macro | SP |
defvar | Macro | SP |
do | Macro | SP |
do* | Macro | SP |
dolist | Macro | SP |
dotimes | Macro | SP |
error | Function | SP |
help | Function | SP |
incf | Macro | SP |
let | Special Form | Built-in |
let* | Special Form | Built-in |
loop | Macro | SP |
pop | Macro | SP |
push | Macro | SP |
quote | Special Form | SP |
setf | Macro | SP |
setq | Special Form | SP |
time | Macro | SP |
trace | Macro | SP |
untrace | Macro | SP |
with-output-to-string | Macro | SP |
上記以外にも、ハードウエア制御などのための uLisp 特有のスペシャルフォームなども多数あり。そのあたりは今回パスということで。
なお、みんな大好き let と let* ですが、ソース上ではビルトインのキーワード枠で、eval処理の内側に隠れていたので独立したスペシャルフォームとか関数にはなっておりませなんだ。結構、奥が深いなuLisp。。。