Next: , Previous: Function, Up: Function Definition   [Contents][Index]

36.3 Macros

関数: buildq (L, expr)

リストLで指名された変数を式 exprに 並列に代入します。exprは評価しません。 buildqが代入を実行した後、 結果の式は整理はされますが、評価されません。

Lの要素はシンボルまたは割り当て式symbol: valueです。 割り当て式は並列に評価されます。 すなわち、ある変数が割り当ての右辺へバインドされるのは、 buildqがコールされた文脈でのバインドです。 変数リストL内でその変数がバインドされるのではありません。 もしLの中のある変数に明示的な割り当てがないなら、 buildqでのバインドは、 buildqがコールされた文脈でのそれと同じです。

そして、Lで指名された変数は並列にexprに代入されます。 すなわち、すべての変数への代入は他の代入がされる前に決まります。 だから、1つの変数の代入は他には一切効果を持ちません。

もし 任意の変数 xexprの中で splice (x)のように現れるなら、 xはリストにバインドされなければいけませんし、 リストは、代入の代わりにexpr に接合(内挿)されます。

exprの中のLに現れない任意の変数は、 たとえそれらがbuildqがコールされた文脈の中でバインドを持っていても、 逐語的に結果に繰り越されます。

aは明示的に xにバインドされ、 一方で bは、コールする文脈で同じバインド(すなわち29)を持ち、 cは逐語的に繰り越されます。 結果の式は、明示的な評価 ''%まで評価されません。

(%i1) (a: 17, b: 29, c: 1729)$
(%i2) buildq ([a: x, b], a + b + c);
(%o2)                      x + c + 29
(%i3) ''%;
(%o3)                       x + 1758

eはリストにバインドされ、 fooの引数の中でそのように現れ、 barの引数の中に内挿されます。

(%i1) buildq ([e: [a, b, c]], foo (x, e, y));
(%o1)                 foo(x, [a, b, c], y)
(%i2) buildq ([e: [a, b, c]], bar (x, splice (e), y));
(%o2)                  bar(x, a, b, c, y)

代入の後、結果は整理されます。 もし代入の前に整理が適用されたら、これら2つの結果は同じになったはずです。

(%i1) buildq ([e: [a, b, c]], splice (e) + splice (e));
(%o1)                    2 c + 2 b + 2 a
(%i2) buildq ([e: [a, b, c]], 2 * splice (e));
(%o2)                        2 a b c

Lの中の変数は並列にバインドされます; もし順次バインドされたなら、 最初の結果は、foo (b, b)になったはずです。 代入は並列に実行されます; 二番目の結果をsubstの結果と比較してください。 substは代入を順次実行します。

(%i1) buildq ([a: b, b: a], foo (a, b));
(%o1)                       foo(b, a)
(%i2) buildq ([u: v, v: w, w: x, x: y, y: z, z: u],
              bar (u, v, w, x, y, z));
(%o2)                 bar(v, w, x, y, z, u)
(%i3) subst ([u=v, v=w, w=x, x=y, y=z, z=u],
             bar (u, v, w, x, y, z));
(%o3)                 bar(u, u, u, u, u, u)

変数や式が左辺に、それらの値が右辺にある等式のリストを構成します。 macroexpandshow_valuesが返す式を表示します。

(%i1) show_values ([L]) ::= buildq ([L], map ("=", 'L, L));
(%o1)   show_values([L]) ::= buildq([L], map("=", 'L, L))
(%i2) (a: 17, b: 29, c: 1729)$
(%i3) show_values (a, b, c - a - b);
(%o3)          [a = 17, b = 29, c - b - a = 1683]
(%i4) macroexpand (show_values (a, b, c - a - b));
(%o4)    map(=, '([a, b, c - b - a]), [a, b, c - b - a])

複数の引数を持つ関数が与えられたとして、 引数のいくつかが固定されたもう1つの関数を生成します。

(%i1) curry (f, [a]) :=
        buildq ([f, a], lambda ([[x]], apply (f, append (a, x))))$
(%i2) by3 : curry ("*", 3);
(%o2)        lambda([[x]], apply(*, append([3], x)))
(%i3) by3 (a + b);
(%o3)                       3 (b + a)
関数: macroexpand (expr)

exprがマクロ関数コールの時、 exprのマクロ展開を、評価はせずに、返します。 そうでなければ、macroexpandexprを返します。

もしexprの展開が別のマクロ関数コールをもたらすなら、 そのマクロ関数コールも展開されます。

macroexpandは引数をクォートします。 しかしながら、もしマクロ関数コールの展開が副作用を持つなら, それらの副作用が実行されます。

::=, macros, macroexpand1も参照してください。

(%i1) g (x) ::= x / 99;
                                    x
(%o1)                      g(x) ::= --
                                    99
(%i2) h (x) ::= buildq ([x], g (x - a));
(%o2)            h(x) ::= buildq([x], g(x - a))
(%i3) a: 1234;
(%o3)                         1234
(%i4) macroexpand (h (y));
                              y - a
(%o4)                         -----
                               99
(%i5) h (y);
                            y - 1234
(%o5)                       --------
                               99
関数: macroexpand1 (expr)

exprがマクロ関数コールの時、 exprのマクロ展開を、評価せずに、返します。 そうでなければ、macroexpand1exprを返します。

macroexpandは引数をクォートします。 しかしながら、もしマクロ関数コールの展開が副作用を持つなら, それらの副作用が実行されます。

もしexprの展開が別のマクロ関数コールをもたらすなら、 そのマクロ関数コールは展開されません。

::=, macros, macroexpandも参照してください。

(%i1) g (x) ::= x / 99;
                                    x
(%o1)                      g(x) ::= --
                                    99
(%i2) h (x) ::= buildq ([x], g (x - a));
(%o2)            h(x) ::= buildq([x], g(x - a))
(%i3) a: 1234;
(%o3)                         1234
(%i4) macroexpand1 (h (y));
(%o4)                       g(y - a)
(%i5) h (y);
                            y - 1234
(%o5)                       --------
                               99
Global variable: macros

デフォルト値: []

macrosは、ユーザー定義のマクロ関数のリストです。 マクロ関数定義演算子::=は、このリストに新しいマクロ関数を入れ、 kill, remove, remfunctionはリストからマクロ関数を削除します。

infolistsも参照してください。

関数: splice (a)

splicebuildq内部に現れた時だけ、 アトムaで指名されたリストを式に接合(内挿)します; そうでなければ、spliceは未定義関数として扱われます。 もし buildq内部で a単独として(spliceなしに)現れたら、 aはリストとして、結果の中に代入されます(内挿されません)。 spliceの引数はアトムだけを取り得ます; リストリテラルやリストをもたらす式を取ることはできません。

通常、spliceは、関数や演算子の引数を提供します。 関数fに対して、 buildq内部の式f (splice (a))は、 f (a[1], a[2], a[3], ...)に展開されます。 演算子oに対して、 buildq内部の式"o" (splice (a)は、 "o" (a[1], a[2], a[3], ...)に展開されます。 ここでoは、任意のタイプの演算子を取り得ます(通常は複数の引数を取るものです)。 演算子はダブルクォート"でくくられなければいけないことに注意してください。

(%i1) buildq ([x: [1, %pi, z - y]], foo (splice (x)) / length (x));
                       foo(1, %pi, z - y)
(%o1)                -----------------------
                     length([1, %pi, z - y])
(%i2) buildq ([x: [1, %pi]], "/" (splice (x)));
                                1
(%o2)                          ---
                               %pi
(%i3) matchfix ("<>", "<>");
(%o3)                          <>
(%i4) buildq ([x: [1, %pi, z - y]], "<>" (splice (x)));
(%o4)                   <>1, %pi, z - y<>

Next: , Previous: Function, Up: Function Definition   [Contents][Index]