20be503cae 2010-11-24 kinaba: Ddoc 20be503cae 2010-11-24 kinaba: $(DDOC_AUTHORS k.inaba) 20be503cae 2010-11-24 kinaba: $(DDOC_LICENSE NYSL 0.9982 (http://www.kmonos.net/nysl/)) 20be503cae 2010-11-24 kinaba: 20be503cae 2010-11-24 kinaba: <p> 20be503cae 2010-11-24 kinaba: このファイルは、言語仕様などの簡単な説明です。 20be503cae 2010-11-24 kinaba: </p> 20be503cae 2010-11-24 kinaba: <p> 20be503cae 2010-11-24 kinaba: あとついでに、左のサイドバーの "Package" タブをクリックすると実装のソースのドキュメントが読めます。 20be503cae 2010-11-24 kinaba: </p> 20be503cae 2010-11-24 kinaba: 20be503cae 2010-11-24 kinaba: $(DDOC_MEMBERS 20be503cae 2010-11-24 kinaba: 20be503cae 2010-11-24 kinaba: $(SECTION Syntax, $(SECBODY 20be503cae 2010-11-24 kinaba: <p> 20be503cae 2010-11-24 kinaba: 文法について。 20be503cae 2010-11-24 kinaba: 字句解析がわりと適当なので、 20be503cae 2010-11-24 kinaba: 変数宣言の変数名のところに、数字を変数名として使えて参照できない変数が作れたり、 20be503cae 2010-11-24 kinaba: 予約語は予約語として解釈され得ないところでは普通に変数名として使えちゃったりして、 20be503cae 2010-11-24 kinaba: 偶にとんでもない見かけのソースが構文解析通りますが、気にしないで適当に使って下さい。 20be503cae 2010-11-24 kinaba: </p> 20be503cae 2010-11-24 kinaba: 20be503cae 2010-11-24 kinaba: $(DDOC_MEMBERS 20be503cae 2010-11-24 kinaba: 20be503cae 2010-11-24 kinaba: $(SECTION 文字コード, $(SECBODY 20be503cae 2010-11-24 kinaba: <p> 20be503cae 2010-11-24 kinaba: UTF-8 のみ対応です。 20be503cae 2010-11-24 kinaba: </p> 20be503cae 2010-11-24 kinaba: )) 20be503cae 2010-11-24 kinaba: 20be503cae 2010-11-24 kinaba: $(SECTION コメント, $(SECBODY 20be503cae 2010-11-24 kinaba: <p> 20be503cae 2010-11-24 kinaba: 行コメントは <tt>#</tt> から改行までです。 20be503cae 2010-11-24 kinaba: </p> 20be503cae 2010-11-24 kinaba: <p> 20be503cae 2010-11-24 kinaba: ブロックコメントはありません。 20be503cae 2010-11-24 kinaba: </p> 20be503cae 2010-11-24 kinaba: )) 20be503cae 2010-11-24 kinaba: 20be503cae 2010-11-24 kinaba: $(SECTION BNF, $(SECBODY 20be503cae 2010-11-24 kinaba: <pre> 20be503cae 2010-11-24 kinaba: ID ::= 適当に識別子っぽい文字列 20be503cae 2010-11-24 kinaba: LAYER ::= "@" ID 20be503cae 2010-11-24 kinaba: 20be503cae 2010-11-24 kinaba: E ::= 20be503cae 2010-11-24 kinaba: $(D_COMMENT # 変数宣言) 20be503cae 2010-11-24 kinaba: | ("var"|"let"|"def"|LAYER) ID "=" E (";"|"in") E 20be503cae 2010-11-24 kinaba: | ("var"|"let"|"def"|LAYER) ID "(" PARAMS ")" "{" E "}" (";"|"in") E 20be503cae 2010-11-24 kinaba: | ("var"|"let"|"def"|LAYER) ID "=" E 20be503cae 2010-11-24 kinaba: | ("var"|"let"|"def"|LAYER) ID "(" PARAMS ")" "{" E "}" 20be503cae 2010-11-24 kinaba: 20be503cae 2010-11-24 kinaba: $(D_COMMENT # リテラル) 20be503cae 2010-11-24 kinaba: | INTEGER $(D_COMMENT # 非負整数) 20be503cae 2010-11-24 kinaba: | STRING $(D_COMMENT # "" でくくった文字列。\" と \\ は使える) 20be503cae 2010-11-24 kinaba: | "{" ENTRYS "}" $(D_COMMENT # テーブル) 20be503cae 2010-11-24 kinaba: | "fun" "(" PARAMS ")" "{" E "}" $(D_COMMENT # 無名関数) 20be503cae 2010-11-24 kinaba: | "λ" "(" PARAMS ")" "{" E "}" $(D_COMMENT # 無名関数) 20be503cae 2010-11-24 kinaba: 20be503cae 2010-11-24 kinaba: $(D_COMMENT # 関数呼び出し) 20be503cae 2010-11-24 kinaba: | E "(" ARGS")" 20be503cae 2010-11-24 kinaba: 20be503cae 2010-11-24 kinaba: where ARGS ::= E "," ... "," E 20be503cae 2010-11-24 kinaba: PARAMS ::= (ID|LAYER)+ "," ... "," (ID|LAYER)+ 20be503cae 2010-11-24 kinaba: ENTRYS ::= ID ":" E "," ... "," ID ":" E 20be503cae 2010-11-24 kinaba: 20be503cae 2010-11-24 kinaba: $(D_COMMENT # 演算子など) 20be503cae 2010-11-24 kinaba: | "(" E ")" $(D_COMMENT # ただの括弧) 20be503cae 2010-11-24 kinaba: | E BINOP E $(D_COMMENT # 二項演算子いろいろ) 20be503cae 2010-11-24 kinaba: | E "." ID $(D_COMMENT # テーブルのフィールドアクセス) 20be503cae 2010-11-24 kinaba: | E ".?" ID $(D_COMMENT # テーブルにフィールドがあるか否か) 20be503cae 2010-11-24 kinaba: | E "{" ENTRYS "}" $(D_COMMENT # テーブル拡張) 3ae09b8cbf 2010-11-24 kinaba: | "if" E ("then"|":"|"then" ":") E 3ae09b8cbf 2010-11-24 kinaba: | "if" E ("then"|":"|"then" ":") E "else" ":"? E 20be503cae 2010-11-24 kinaba: 20be503cae 2010-11-24 kinaba: $(D_COMMENT # パターンマッチ) 3ae09b8cbf 2010-11-24 kinaba: | "case" E ("when" PATTERN ":" E )* 20be503cae 2010-11-24 kinaba: 20be503cae 2010-11-24 kinaba: where PATTERN ::= 式がだいたいなんでも書ける気がする 20be503cae 2010-11-24 kinaba: 20be503cae 2010-11-24 kinaba: $(D_COMMENT # レイヤ指定実行) 20be503cae 2010-11-24 kinaba: | LAYER "(" E ")" 20be503cae 2010-11-24 kinaba: </pre> 20be503cae 2010-11-24 kinaba: )) 20be503cae 2010-11-24 kinaba: 20be503cae 2010-11-24 kinaba: $(SECTION 糖衣構文, $(SECBODY 20be503cae 2010-11-24 kinaba: <p> 20be503cae 2010-11-24 kinaba: 演算子というものはありません。内部的には全て関数呼び出し構文に書き換えられています。<tt>if</tt> もです。 20be503cae 2010-11-24 kinaba: <br/> 20be503cae 2010-11-24 kinaba: パターンマッチも全部 <tt>if</tt> と <tt>==</tt> と <tt>&&</tt> と 20be503cae 2010-11-24 kinaba: <tt>.</tt> と <tt>.?</tt> を使った関数呼び出し式に書き換えられていますが、 20be503cae 2010-11-24 kinaba: 規則の詳細を説明するのが面倒なので適当に想像して下さい。 20be503cae 2010-11-24 kinaba: 他の書き換えはこんな感じです。 20be503cae 2010-11-24 kinaba: </p> 20be503cae 2010-11-24 kinaba: <pre> 3ae09b8cbf 2010-11-24 kinaba: if E then E ⇒ if( E, fun(){E}, fun(){} ) 3ae09b8cbf 2010-11-24 kinaba: if E then E else E ⇒ if( E, fun(){E}, fun(){E} ) 8caee17864 2010-11-24 kinaba: E BINOP E ⇒ BINOP(E, E) 8caee17864 2010-11-24 kinaba: { ENTRIES } ⇒ {}{ ENTRIES } 8caee17864 2010-11-24 kinaba: {} ⇒ {}() 8caee17864 2010-11-24 kinaba: E {ID:E, ...} ⇒ .=(E, ID, E) { ... } 20be503cae 2010-11-24 kinaba: </pre> 20be503cae 2010-11-24 kinaba: <p> 20be503cae 2010-11-24 kinaba: 変数宣言に色々ありますが、<tt>let</tt> と <tt>var</tt> と <tt>def</tt> は同じ扱いで、 20be503cae 2010-11-24 kinaba: <tt>in</tt> と <tt>;</tt> は同じ扱いです。つまり 20be503cae 2010-11-24 kinaba: </p> 20be503cae 2010-11-24 kinaba: <pre> 20be503cae 2010-11-24 kinaba: let x = E in E 20be503cae 2010-11-24 kinaba: var x = E in E 20be503cae 2010-11-24 kinaba: def x = E in E 20be503cae 2010-11-24 kinaba: let x = E ; E 20be503cae 2010-11-24 kinaba: var x = E ; E 20be503cae 2010-11-24 kinaba: def x = E ; E 20be503cae 2010-11-24 kinaba: </pre> 20be503cae 2010-11-24 kinaba: <p> 20be503cae 2010-11-24 kinaba: 以上のどれも同じ意味なので、なんとなく関数型っぽく書きたい気分の日は <tt>let in</tt> を、 3ae09b8cbf 2010-11-24 kinaba: 手続き型っぽく書きたい気分の日は <tt>var ;</tt> を使うとよいと思います。 3ae09b8cbf 2010-11-24 kinaba: <tt>if then else</tt> も微妙にコロンがあったりなかったりバリエーションがありますが好みで使います。 20be503cae 2010-11-24 kinaba: </p> 20be503cae 2010-11-24 kinaba: <p> 20be503cae 2010-11-24 kinaba: 関数を宣言するときは、<tt>fun</tt> や <tt>λ</tt> を省略できます。 20be503cae 2010-11-24 kinaba: 以下の書き換えが行われます。 20be503cae 2010-11-24 kinaba: </p> 20be503cae 2010-11-24 kinaba: <pre> 20be503cae 2010-11-24 kinaba: def f( ARGS ) { E }; E ⇒ def f = fun(ARGS){E}; E 20be503cae 2010-11-24 kinaba: </pre> 20be503cae 2010-11-24 kinaba: <p> 20be503cae 2010-11-24 kinaba: 他に、もっと手続き型っぽくための書き換え色々 20be503cae 2010-11-24 kinaba: </p> 20be503cae 2010-11-24 kinaba: <pre> 20be503cae 2010-11-24 kinaba: fun () { E; E; E } ⇒ fun () { let _ = E in let _ = E in E } 20be503cae 2010-11-24 kinaba: fun () { var x = 100 } ⇒ fun () { var x = 100; x } 20be503cae 2010-11-24 kinaba: fun () { var x = 100; } ⇒ fun () { var x = 100; x } 20be503cae 2010-11-24 kinaba: fun () { } ⇒ fun () { "(empty function body)" } 20be503cae 2010-11-24 kinaba: </pre> 20be503cae 2010-11-24 kinaba: <p> 20be503cae 2010-11-24 kinaba: 中身が空の関数に何を返させるかは適当です。今はとりあえず適当に文字列返してます。 20be503cae 2010-11-24 kinaba: </p> 20be503cae 2010-11-24 kinaba: )) 20be503cae 2010-11-24 kinaba: 20be503cae 2010-11-24 kinaba: $(SECTION 変数のスコープ規則, $(SECBODY 20be503cae 2010-11-24 kinaba: <p> 8caee17864 2010-11-24 kinaba: 基本的には、let によって常識的な感じに変数のスコープがネストします。 8caee17864 2010-11-24 kinaba: </p> 8caee17864 2010-11-24 kinaba: <pre> 8caee17864 2010-11-24 kinaba: let x=21 in let x=x+x in x $(D_COMMENT # 42) 8caee17864 2010-11-24 kinaba: </pre> 8caee17864 2010-11-24 kinaba: <p> 8caee17864 2010-11-24 kinaba: 一方で、"let rec" のような特別な構文はありませんが、 8caee17864 2010-11-24 kinaba: </p> 8caee17864 2010-11-24 kinaba: <pre> 3ae09b8cbf 2010-11-24 kinaba: let f = fun(x) { if x==0 then 1 else x*f(x-1) } in f(10) $(D_COMMENT # 3628800) 8caee17864 2010-11-24 kinaba: </pre> 8caee17864 2010-11-24 kinaba: <p> 8caee17864 2010-11-24 kinaba: 再帰的な関数定義なども、おそらく意図されたとおりに動きます。 8caee17864 2010-11-24 kinaba: 内部の詳細は、諸般の事情により、 8caee17864 2010-11-24 kinaba: マジカルで破壊的なスコープ規則になっているのですが、 8caee17864 2010-11-24 kinaba: 同名の変数を激しく重ねて使ったりしなければ、 8caee17864 2010-11-24 kinaba: だいたい自然な動きをすると思います、たぶん、はい。 8caee17864 2010-11-24 kinaba: </p> 8caee17864 2010-11-24 kinaba: <p> 8caee17864 2010-11-24 kinaba: ひとつだけ不可思議な動きをするのは、以下のケースです。 8caee17864 2010-11-24 kinaba: </p> 8caee17864 2010-11-24 kinaba: <pre> 8caee17864 2010-11-24 kinaba: let x = 1 in 8caee17864 2010-11-24 kinaba: let f = fun() {x} in 8caee17864 2010-11-24 kinaba: let x = 2 in 8caee17864 2010-11-24 kinaba: f() $(D_COMMENT # 2!!) 8caee17864 2010-11-24 kinaba: </pre> 8caee17864 2010-11-24 kinaba: <p> 8caee17864 2010-11-24 kinaba: let-in を縦にチェインしたときだけ、同名変数を破壊的に上書きします 8caee17864 2010-11-24 kinaba: (再帰関数の定義が"うまく"いっているのはこの上書きのためです)。 8caee17864 2010-11-24 kinaba: なんでこんなことになっているかというと、 8caee17864 2010-11-24 kinaba: 後で説明する「レイヤ」を使ったときに 8caee17864 2010-11-24 kinaba: <tt>let foo = ... in @lay foo = ... in ...</tt> 8caee17864 2010-11-24 kinaba: で他レイヤに重ね書きするためであります。 20be503cae 2010-11-24 kinaba: </p> 20be503cae 2010-11-24 kinaba: )) 8caee17864 2010-11-24 kinaba: ) 20be503cae 2010-11-24 kinaba: )) 20be503cae 2010-11-24 kinaba: 20be503cae 2010-11-24 kinaba: 20be503cae 2010-11-24 kinaba: 20be503cae 2010-11-24 kinaba: 20be503cae 2010-11-24 kinaba: $(SECTION Basic Features, $(SECBODY 20be503cae 2010-11-24 kinaba: <p> 20be503cae 2010-11-24 kinaba: 特に特徴的でもない部分を簡単にまとめ。 20be503cae 2010-11-24 kinaba: </p> 20be503cae 2010-11-24 kinaba: <ul> 20be503cae 2010-11-24 kinaba: <li>静的型システムはありません。</li> 20be503cae 2010-11-24 kinaba: <li>"ほぼ" 純粋関数型言語です。変数やテーブルのフィールドの破壊的な書き換えはできません。<br/> 20be503cae 2010-11-24 kinaba: ただし、組み込み関数(<tt>print</tt>)と、変数のスコープ規則のマジカルな片隅に副作用があります。</li> 20be503cae 2010-11-24 kinaba: </ul> 20be503cae 2010-11-24 kinaba: <p> 20be503cae 2010-11-24 kinaba: 静的型システムがないのは意図的ですが、破壊的代入がないのは、単に実装がめんどかっただけなので、 20be503cae 2010-11-24 kinaba: 今後何か増えるかもしれません。増えないかもしれません。 20be503cae 2010-11-24 kinaba: </p> 20be503cae 2010-11-24 kinaba: $(DDOC_MEMBERS 20be503cae 2010-11-24 kinaba: $(SECTION データ型, $(SECBODY 20be503cae 2010-11-24 kinaba: <p> 20be503cae 2010-11-24 kinaba: 以下のデータ型があります。 20be503cae 2010-11-24 kinaba: </p> 20be503cae 2010-11-24 kinaba: <ul> 20be503cae 2010-11-24 kinaba: <li>整数: <tt>0</tt>, <tt>123</tt>, <tt>456666666666666666666666666666666666666789</tt>, ...</li> 20be503cae 2010-11-24 kinaba: <li>文字列: <tt>"hello, world!"</tt>, ...</li> 20be503cae 2010-11-24 kinaba: <li>関数: <tt>fun(x){x+1}</tt></li> 20be503cae 2010-11-24 kinaba: <li>テーブル: <tt>{car: 1, cdr: {car: 2, cdr: {}}}</tt></li> c0158c9281 2010-11-24 kinaba: <li>未定義値: (undefined。特殊なケースで作られます)</li> 20be503cae 2010-11-24 kinaba: </ul> 20be503cae 2010-11-24 kinaba: <p> 20be503cae 2010-11-24 kinaba: 関数はいわゆる「クロージャ」です。静的スコープで外側の環境にアクセスできます。 20be503cae 2010-11-24 kinaba: テーブルはいわゆるプロトタイプチェーンを持っていて、 20be503cae 2010-11-24 kinaba: 自分にないフィールドの場合は親に問い合わせが行く感じになっていますが、 20be503cae 2010-11-24 kinaba: フィールドの書き換えがないので、これは特に意味ないかもしれない…。 c0158c9281 2010-11-24 kinaba: </p> c0158c9281 2010-11-24 kinaba: <p> c0158c9281 2010-11-24 kinaba: また、リストを扱うために、いわゆる「cons リスト」を使います。 c0158c9281 2010-11-24 kinaba: 空リストを <tt>{}</tt>、1個以上要素があるものを <tt>{car: 先頭要素, cdr: 二番目以降のリスト}</tt> c0158c9281 2010-11-24 kinaba: という形で。この形でリストを扱わなければならないという決まりはありませんが、 c0158c9281 2010-11-24 kinaba: この形は特別扱いされて <tt>print</tt> で綺麗に出力されたりします。 8caee17864 2010-11-24 kinaba: </p> 20be503cae 2010-11-24 kinaba: )) 20be503cae 2010-11-24 kinaba: $(SECTION パターンマッチ, $(SECBODY 8caee17864 2010-11-24 kinaba: <p> 8caee17864 2010-11-24 kinaba: 適当に実装されたパターンマッチがあります。 8caee17864 2010-11-24 kinaba: リストの 2n 番目と 2n+1 番目を足して長さを半分にする関数: 8caee17864 2010-11-24 kinaba: </p> 8caee17864 2010-11-24 kinaba: <pre> 8caee17864 2010-11-24 kinaba: def adjSum(lst) 8caee17864 2010-11-24 kinaba: { 3ae09b8cbf 2010-11-24 kinaba: case lst 3ae09b8cbf 2010-11-24 kinaba: when {car:x, cdr:{car: y, cdr:z}}: {car: x+y, cdr: adjSum(z)} 3ae09b8cbf 2010-11-24 kinaba: when {car:x, cdr:{}}: lst 3ae09b8cbf 2010-11-24 kinaba: when {}: {} 8caee17864 2010-11-24 kinaba: } 8caee17864 2010-11-24 kinaba: </pre> 8caee17864 2010-11-24 kinaba: <p> 8caee17864 2010-11-24 kinaba: 動かすときには、処理系がそれっぽい if-then-else に展開しています。 8caee17864 2010-11-24 kinaba: <tt>when</tt> を上から試していって、最初にマッチしたところを実行します。 8caee17864 2010-11-24 kinaba: </p> 8caee17864 2010-11-24 kinaba: <pre> 8caee17864 2010-11-24 kinaba: PAT ::= "_" $(D_COMMENT # ワイルドカード) 8caee17864 2010-11-24 kinaba: | ID $(D_COMMENT # 変数パターン) 8caee17864 2010-11-24 kinaba: | "{" ID ":" PAT "," ... "," ID : PAT "}" $(D_COMMENT # テーブルパターン) 8caee17864 2010-11-24 kinaba: | E $(D_COMMENT # 値パターン) 8caee17864 2010-11-24 kinaba: </pre> 8caee17864 2010-11-24 kinaba: <p> 8caee17864 2010-11-24 kinaba: 変数パターンは常にマッチして、値をその変数に束縛します。 8caee17864 2010-11-24 kinaba: ワイルドカードも常にマッチしますが、変数束縛しません。 8caee17864 2010-11-24 kinaba: 値パターンは、任意の式が書けます。その式を評価した結果と <tt>==</tt> ならマッチします。 8caee17864 2010-11-24 kinaba: 外で束縛された変数を値パターンとして配置、は直接はできないので 8caee17864 2010-11-24 kinaba: </p> 8caee17864 2010-11-24 kinaba: <pre> 8caee17864 2010-11-24 kinaba: var x = 123; 3ae09b8cbf 2010-11-24 kinaba: case foo 3ae09b8cbf 2010-11-24 kinaba: when {val: x+0}: ... $(D_COMMENT # これは {val:123} と同じ) 3ae09b8cbf 2010-11-24 kinaba: when {val: x}: ... $(D_COMMENT # これは任意の foo.?val なら常にマッチ) 8caee17864 2010-11-24 kinaba: </pre> 8caee17864 2010-11-24 kinaba: <p> 8caee17864 2010-11-24 kinaba: 適当にちょっと複雑な式にしてやるとよいかも(裏技)。 8caee17864 2010-11-24 kinaba: </p> 8caee17864 2010-11-24 kinaba: <p> 8caee17864 2010-11-24 kinaba: テーブルパターンは、書かれたキーが全てあればマッチします。 8caee17864 2010-11-24 kinaba: <tt>{a: _}</tt> は、<tt>.a</tt> を持ってさえいればマッチするので、 8caee17864 2010-11-24 kinaba: <tt>{a: 123, b: 456}</tt> なんかにもマッチします。 8caee17864 2010-11-24 kinaba: なので、リストに対するパターンを書くときには、car/cdr の場合を先に書かないと 3ae09b8cbf 2010-11-24 kinaba: <tt>when {}</tt> を上に書くと全部マッチしちゃいます。注意。 8caee17864 2010-11-24 kinaba: </p> 20be503cae 2010-11-24 kinaba: )) 20be503cae 2010-11-24 kinaba: ) 20be503cae 2010-11-24 kinaba: )) 20be503cae 2010-11-24 kinaba: 20be503cae 2010-11-24 kinaba: 20be503cae 2010-11-24 kinaba: 20be503cae 2010-11-24 kinaba: 20be503cae 2010-11-24 kinaba: 20be503cae 2010-11-24 kinaba: $(SECTION Layers, $(SECBODY 20be503cae 2010-11-24 kinaba: <pre> 20be503cae 2010-11-24 kinaba: [Layers :: Overview] 20be503cae 2010-11-24 kinaba: 20be503cae 2010-11-24 kinaba: Polemy's runtime environment has many "layer"s. 20be503cae 2010-11-24 kinaba: Usual execution run in the @value layer. 20be503cae 2010-11-24 kinaba: 20be503cae 2010-11-24 kinaba: >> 1 + 2 20be503cae 2010-11-24 kinaba: 3 20be503cae 2010-11-24 kinaba: >> @value( 1 + 2 ) 20be503cae 2010-11-24 kinaba: 3 20be503cae 2010-11-24 kinaba: 20be503cae 2010-11-24 kinaba: Here you can see that @LayerName( Expression ) executes the inner Expression in 20be503cae 2010-11-24 kinaba: the @LayerName layer. Other than @value, one other predefined layer exists: @macro. 20be503cae 2010-11-24 kinaba: 20be503cae 2010-11-24 kinaba: >> @macro( 1+2 ) 20be503cae 2010-11-24 kinaba: {pos@value:{lineno@value:3, column@value:9, filename@value:<REPL>}, 20be503cae 2010-11-24 kinaba: is@value:app, 20be503cae 2010-11-24 kinaba: args@value:{car@value:{pos@value:{lineno@value:3, column@value:9, filename@value:<REPL>}, 20be503cae 2010-11-24 kinaba: is@value:int, 20be503cae 2010-11-24 kinaba: data@value:1}, 20be503cae 2010-11-24 kinaba: cdr@value:{ 20be503cae 2010-11-24 kinaba: car@value:{pos@value:{lineno@value:3, column@value:11, filename@value:<REPL>}, 20be503cae 2010-11-24 kinaba: is@value:int, 20be503cae 2010-11-24 kinaba: data@value:2}, 20be503cae 2010-11-24 kinaba: cdr@value:{}}}, 20be503cae 2010-11-24 kinaba: fun@value:{pos@value:{lineno@value:3, column@value:10, filename@value:<REPL>}, 20be503cae 2010-11-24 kinaba: is@value:var, 20be503cae 2010-11-24 kinaba: name@value:+}} 20be503cae 2010-11-24 kinaba: 20be503cae 2010-11-24 kinaba: (Sorry, this pretty printing is not available on the actual interpreter...) 20be503cae 2010-11-24 kinaba: This evaluates the expression 1+2 in the @macro layer. In this layer, the meaning of 20be503cae 2010-11-24 kinaba: the program is its abstract syntax tree. 20be503cae 2010-11-24 kinaba: 20be503cae 2010-11-24 kinaba: You can interleave layers. 20be503cae 2010-11-24 kinaba: The root node of the abstract syntax tree is function "app"lication. 20be503cae 2010-11-24 kinaba: 20be503cae 2010-11-24 kinaba: >> @value(@macro( 1+2 ).is) 20be503cae 2010-11-24 kinaba: app 20be503cae 2010-11-24 kinaba: 20be503cae 2010-11-24 kinaba: 20be503cae 2010-11-24 kinaba: 20be503cae 2010-11-24 kinaba: [Layers :: Defining a new layer] 20be503cae 2010-11-24 kinaba: 20be503cae 2010-11-24 kinaba: To define a new layer, you should first tell how to "lift" existing values two the new layer. 20be503cae 2010-11-24 kinaba: Let us define the "@type" layer, where the meaning of programs is their static type. 20be503cae 2010-11-24 kinaba: 20be503cae 2010-11-24 kinaba: >> @@type = fun(x) { 20be503cae 2010-11-24 kinaba: >> if( _isint(x) ) { "int" } else { 20be503cae 2010-11-24 kinaba: >> if( _isfun(x) ) { x } else { "unknown" } } 20be503cae 2010-11-24 kinaba: >> } 20be503cae 2010-11-24 kinaba: (Note: polemy REPL may warn some exception here but please ignore) 20be503cae 2010-11-24 kinaba: 20be503cae 2010-11-24 kinaba: For simplicity, I here deal only with integers. 20be503cae 2010-11-24 kinaba: _isint is a primitive function of Polemy that checks the dynamic type of a value. 20be503cae 2010-11-24 kinaba: For function, leaving it untouched works well for almost all layers. 20be503cae 2010-11-24 kinaba: 20be503cae 2010-11-24 kinaba: >> @type( 1 ) 20be503cae 2010-11-24 kinaba: int 20be503cae 2010-11-24 kinaba: >> @type( 2 ) 20be503cae 2010-11-24 kinaba: int 20be503cae 2010-11-24 kinaba: >> @type( "foo" ) 20be503cae 2010-11-24 kinaba: unknown 20be503cae 2010-11-24 kinaba: 20be503cae 2010-11-24 kinaba: Fine! Let's try to type 1+2. 20be503cae 2010-11-24 kinaba: 20be503cae 2010-11-24 kinaba: >> @type( 1 + 2 ) 20be503cae 2010-11-24 kinaba: ...\value.d(119): [<REPL>:6:8] only @value layer can call native function 20be503cae 2010-11-24 kinaba: 20be503cae 2010-11-24 kinaba: Note that the behavior of this program is 20be503cae 2010-11-24 kinaba: - run 1+2 in the @type layer 20be503cae 2010-11-24 kinaba: and NOT 20be503cae 2010-11-24 kinaba: - run 1+2 in @value and obtain 3 and run 3 in the @type. 20be503cae 2010-11-24 kinaba: The problem is, the variable "+" is defined only in the @value layer. 20be503cae 2010-11-24 kinaba: To carry out computation in the @type layer. We need to define it also 20be503cae 2010-11-24 kinaba: in the @type layer. 20be503cae 2010-11-24 kinaba: 20be503cae 2010-11-24 kinaba: To define some variable in a specific layer, use @LayerName in place of 20be503cae 2010-11-24 kinaba: (let|var|def)s. 20be503cae 2010-11-24 kinaba: 20be503cae 2010-11-24 kinaba: >> let x = 2 20be503cae 2010-11-24 kinaba: >> @value x = 2 20be503cae 2010-11-24 kinaba: >> @type x = "int" 20be503cae 2010-11-24 kinaba: >> @hoge x = "fuga" 20be503cae 2010-11-24 kinaba: 20be503cae 2010-11-24 kinaba: For "+", do it like this. 20be503cae 2010-11-24 kinaba: 20be503cae 2010-11-24 kinaba: >> @type "+" = fun(x,y) {@value( 20be503cae 2010-11-24 kinaba: >> if( @type(x)=="int" && @type(y)=="int" ) { "int" } else { "typeerror" } 20be503cae 2010-11-24 kinaba: >> )} 20be503cae 2010-11-24 kinaba: polemy.value.native!(IntValue,IntValue,IntValue).native.__anonclass24 20be503cae 2010-11-24 kinaba: 20be503cae 2010-11-24 kinaba: It is just computing the return type from the input type. 20be503cae 2010-11-24 kinaba: Not here that the intended "meaning" of if-then-else is the runtime-branching, 20be503cae 2010-11-24 kinaba: and the meaning of "==" is the value-comparison. These are the @value layer 20be503cae 2010-11-24 kinaba: behavior. So we have defined the function body inside @value layer. 20be503cae 2010-11-24 kinaba: But when we refer the variables x and y, we need its @type layer meaning. 20be503cae 2010-11-24 kinaba: Hence we use @type() there. 20be503cae 2010-11-24 kinaba: 20be503cae 2010-11-24 kinaba: Now we get it. 20be503cae 2010-11-24 kinaba: 20be503cae 2010-11-24 kinaba: >> @type( 1 + 2 ) 20be503cae 2010-11-24 kinaba: int 20be503cae 2010-11-24 kinaba: 20be503cae 2010-11-24 kinaba: Well, but do we have to define the @type layer meaning for every variables??? 20be503cae 2010-11-24 kinaba: No. After you defined @type "+", you'll automatically get the following: 20be503cae 2010-11-24 kinaba: 20be503cae 2010-11-24 kinaba: >> def double(x) { x + x } 20be503cae 2010-11-24 kinaba: (function:17e4740:1789720) 20be503cae 2010-11-24 kinaba: 20be503cae 2010-11-24 kinaba: >> @type( double(123) ) 20be503cae 2010-11-24 kinaba: int 20be503cae 2010-11-24 kinaba: 20be503cae 2010-11-24 kinaba: Every user-defined functions are automatically "lift"ed to the appropriate layer. 20be503cae 2010-11-24 kinaba: Only primitive functions like "+" requires @yourNewLayer annotation. 20be503cae 2010-11-24 kinaba: 20be503cae 2010-11-24 kinaba: 20be503cae 2010-11-24 kinaba: 20be503cae 2010-11-24 kinaba: [Layers :: neutral-layer] 20be503cae 2010-11-24 kinaba: 20be503cae 2010-11-24 kinaba: let|var|def is to define a variable in the "current" layer. 20be503cae 2010-11-24 kinaba: Not necessary to the @value layer. 20be503cae 2010-11-24 kinaba: 20be503cae 2010-11-24 kinaba: >> @value( let x = 1 in @value(x) ) 20be503cae 2010-11-24 kinaba: 1 20be503cae 2010-11-24 kinaba: 20be503cae 2010-11-24 kinaba: >> @macro( let x = 1 in @value(x) ) 20be503cae 2010-11-24 kinaba: polemy.failure.RuntimeException: [<REPL>:14:29] variable x not found 20be503cae 2010-11-24 kinaba: 20be503cae 2010-11-24 kinaba: >> @macro( let x = 1 in @macro(x) ) 20be503cae 2010-11-24 kinaba: {pos@value:{lineno@value:15, ... 20be503cae 2010-11-24 kinaba: 20be503cae 2010-11-24 kinaba: 20be503cae 2010-11-24 kinaba: 20be503cae 2010-11-24 kinaba: [Layers :: Layered-Parameters] 20be503cae 2010-11-24 kinaba: 20be503cae 2010-11-24 kinaba: >> def foo(x @macro @value) { {fst: x, snd: @macro(x)} } 20be503cae 2010-11-24 kinaba: (function:1730360:1789720) 20be503cae 2010-11-24 kinaba: 20be503cae 2010-11-24 kinaba: If you annotate function parameters by @LayerNames, when you invoke the function... 20be503cae 2010-11-24 kinaba: 20be503cae 2010-11-24 kinaba: >> foo(1+2) 20be503cae 2010-11-24 kinaba: {snd@value: {pos@value:{lineno@value:17, column@value:5, filename@value:<REPL>}, 20be503cae 2010-11-24 kinaba: is@value:app, arg@value:{... 20be503cae 2010-11-24 kinaba: /fst@value:3 20be503cae 2010-11-24 kinaba: /} 20be503cae 2010-11-24 kinaba: 20be503cae 2010-11-24 kinaba: its corresponding arguments are evaluated in the layer and passed to it. 20be503cae 2010-11-24 kinaba: If you specify multiple layers, the argument expression is run multiple times. 20be503cae 2010-11-24 kinaba: If you do not specify any layer for a parameter, it works in the neutral layer. 8caee17864 2010-11-24 kinaba: </pre> 8caee17864 2010-11-24 kinaba: )) 20be503cae 2010-11-24 kinaba: 20be503cae 2010-11-24 kinaba: 8caee17864 2010-11-24 kinaba: $(SECTION Macro Layers, $(SECBODY 8caee17864 2010-11-24 kinaba: <p> 8caee17864 2010-11-24 kinaba: Polemy 言語組み込みのレイヤは <code>@value</code> と <code>@macro</code> の二つです。 8caee17864 2010-11-24 kinaba: (内部的にはもういくつかありますが、ユーザから直接は使えません。) 8caee17864 2010-11-24 kinaba: <code>@value</code> は、「普通に」普通のセマンティクスでプログラムを実行するレイヤでした。 8caee17864 2010-11-24 kinaba: <code>@macro</code> は、実は、<code>@value</code> よりも前に実行されるレイヤで、 8caee17864 2010-11-24 kinaba: 「プログラムを実行するとその構文木を返す」というセマンティクスで動きます。 8caee17864 2010-11-24 kinaba: </p> 8caee17864 2010-11-24 kinaba: <pre> 8caee17864 2010-11-24 kinaba: (ここに例) 8caee17864 2010-11-24 kinaba: </pre> 8caee17864 2010-11-24 kinaba: <p> 8caee17864 2010-11-24 kinaba: 動きとしてはこうです。 8caee17864 2010-11-24 kinaba: </p> 8caee17864 2010-11-24 kinaba: <ol> 8caee17864 2010-11-24 kinaba: <li>関数呼び出し時(とトップレベル環境の実行開始時)に、 8caee17864 2010-11-24 kinaba: まず、<code>@macro</code> レイヤでコードを実行。</li> 8caee17864 2010-11-24 kinaba: <li>返ってきた構文木を、<code>@value</code> レイヤ、 8caee17864 2010-11-24 kinaba: またはその関数を呼び出したときのレイヤで実行。</li> 8caee17864 2010-11-24 kinaba: </ol> 8caee17864 2010-11-24 kinaba: <p> 8caee17864 2010-11-24 kinaba: <code>@macro</code> レイヤも所詮ただのレイヤですので、 8caee17864 2010-11-24 kinaba: 上で説明した方法で <code>@macro</code> レイヤに関数などを登録しておくことで、 8caee17864 2010-11-24 kinaba: 構文木の生成をいじることが可能です。まさにマクロ。 8caee17864 2010-11-24 kinaba: </p> 20be503cae 2010-11-24 kinaba: 8caee17864 2010-11-24 kinaba: $(DDOC_MEMBERS 8caee17864 2010-11-24 kinaba: $(SECTION 使い方, $(SECBODY 8caee17864 2010-11-24 kinaba: <pre> 20be503cae 2010-11-24 kinaba: When function is invoked, it first run in the @macro layer, and after that, 20be503cae 2010-11-24 kinaba: it run in the neutral layer. Here is an example. 20be503cae 2010-11-24 kinaba: 20be503cae 2010-11-24 kinaba: >> @macro twice(x) { x; x } 20be503cae 2010-11-24 kinaba: >> def f() { twice(print("Hello")); 999 } 20be503cae 2010-11-24 kinaba: (function:173b6a0:1789720) 20be503cae 2010-11-24 kinaba: >> f() 20be503cae 2010-11-24 kinaba: Hello 20be503cae 2010-11-24 kinaba: Hello 20be503cae 2010-11-24 kinaba: 999 20be503cae 2010-11-24 kinaba: 20be503cae 2010-11-24 kinaba: When the interpreter evaluates f(), it first executes 20be503cae 2010-11-24 kinaba: "twice(print("Hello")); 999" 20be503cae 2010-11-24 kinaba: in the @macro layer. Basically what it does is to just construct its syntax tree. 20be503cae 2010-11-24 kinaba: But, since we have defined the "twice" function in the @macro layer, it is 20be503cae 2010-11-24 kinaba: execute as a function. Resulting syntax tree is 20be503cae 2010-11-24 kinaba: "print("Hello"); print("Hello"); 999" 20be503cae 2010-11-24 kinaba: and this is executed on the neutral (in this example, @value) layer. 20be503cae 2010-11-24 kinaba: This is the reason why you see two "Hello"s. 20be503cae 2010-11-24 kinaba: 8caee17864 2010-11-24 kinaba: [[quote and unquote]] 20be503cae 2010-11-24 kinaba: 8caee17864 2010-11-24 kinaba: Here is more involved example of code genration. 8caee17864 2010-11-24 kinaba: From "x", it generates "x*x*x*x*x*x*x*x*x*x". 8caee17864 2010-11-24 kinaba: 8caee17864 2010-11-24 kinaba: @macro pow10(x) { 8caee17864 2010-11-24 kinaba: @value( 8caee17864 2010-11-24 kinaba: def pow(x, n) { 8caee17864 2010-11-24 kinaba: if( n == 1 ) { x } 8caee17864 2010-11-24 kinaba: else { 8caee17864 2010-11-24 kinaba: @macro( @value(x) * @value(pow(x,n-1)) ) 8caee17864 2010-11-24 kinaba: } 8caee17864 2010-11-24 kinaba: } 8caee17864 2010-11-24 kinaba: in 8caee17864 2010-11-24 kinaba: pow(@macro(x),10) 8caee17864 2010-11-24 kinaba: ) 8caee17864 2010-11-24 kinaba: }; 8caee17864 2010-11-24 kinaba: 8caee17864 2010-11-24 kinaba: Here, x is a syntax tree but n is an actual integer. If you read carefully, 8caee17864 2010-11-24 kinaba: you should get what is going on. Basically, @macro can be considered like 8caee17864 2010-11-24 kinaba: quasiquoting and @value to be an escape from it. 8caee17864 2010-11-24 kinaba: </pre> c0158c9281 2010-11-24 kinaba: <p> c0158c9281 2010-11-24 kinaba: 構文木がどのようなテーブルで渡されてくるかについては、ソースドキュメントの c0158c9281 2010-11-24 kinaba: <a href="http://www.kmonos.net/repos/polemy/doc/tip/doc/ast.html">polemy.ast</a> c0158c9281 2010-11-24 kinaba: のページをご覧下さい。例えば変数名を表す <code>Var</code> クラスには、 c0158c9281 2010-11-24 kinaba: 継承の分も合わせて c0158c9281 2010-11-24 kinaba: <tt><a href="http://www.kmonos.net/repos/polemy/doc/tip/doc/failure.html">LexPosition</a> pos;</tt> c0158c9281 2010-11-24 kinaba: と <tt>string name;</tt> の2つのメンバがあるので c0158c9281 2010-11-24 kinaba: </p> c0158c9281 2010-11-24 kinaba: <pre> c0158c9281 2010-11-24 kinaba: { is: "Var", c0158c9281 2010-11-24 kinaba: pos: {filename:"foo.pmy", lineno:123, column:45}, c0158c9281 2010-11-24 kinaba: name: "x" } c0158c9281 2010-11-24 kinaba: </pre> c0158c9281 2010-11-24 kinaba: <p> c0158c9281 2010-11-24 kinaba: こんな感じのテーブルになります。 c0158c9281 2010-11-24 kinaba: クラス名が <tt>is</tt> フィールドに、メンバ変数はそのままの名前で入ります。 c0158c9281 2010-11-24 kinaba: 配列メンバは cons リストになって入ってきます。 c0158c9281 2010-11-24 kinaba: </p> 8caee17864 2010-11-24 kinaba: )) 8caee17864 2010-11-24 kinaba: $(SECTION 微妙な挙動, $(SECBODY 8caee17864 2010-11-24 kinaba: <pre> 8caee17864 2010-11-24 kinaba: (rawmacro) レイヤの話 20be503cae 2010-11-24 kinaba: 20be503cae 2010-11-24 kinaba: [[limitations]] 20be503cae 2010-11-24 kinaba: 20be503cae 2010-11-24 kinaba: This @macro layer is a very primitive one, and not a perfect macro language. 20be503cae 2010-11-24 kinaba: Two major limitations are seen in the following "it" example. 20be503cae 2010-11-24 kinaba: 20be503cae 2010-11-24 kinaba: >> @macro LetItBe(x, y) { let it = x in y }; 20be503cae 2010-11-24 kinaba: 20be503cae 2010-11-24 kinaba: The variable name is not hygenic, and so without any effort, the syntax tree "y" 20be503cae 2010-11-24 kinaba: can access the outer variable "it". 20be503cae 2010-11-24 kinaba: 20be503cae 2010-11-24 kinaba: >> def foo() { LetItBe( 1+2+3, it*it ) } 20be503cae 2010-11-24 kinaba: >> foo() 20be503cae 2010-11-24 kinaba: 36 20be503cae 2010-11-24 kinaba: 20be503cae 2010-11-24 kinaba: Of course, this is not just a limitation; it can sometimes allow us to write 20be503cae 2010-11-24 kinaba: many interesting macros. 20be503cae 2010-11-24 kinaba: 20be503cae 2010-11-24 kinaba: The other problem is that the macro expansion is only done at function startup. 20be503cae 2010-11-24 kinaba: So 20be503cae 2010-11-24 kinaba: 20be503cae 2010-11-24 kinaba: >> LetItBe( 1+2+3, it*it ) 20be503cae 2010-11-24 kinaba: ...\value.d(173): [<REPL>:24:1] variable LetItBe is not set in layer @value 20be503cae 2010-11-24 kinaba: 20be503cae 2010-11-24 kinaba: you cannot directly use the macro in the same scope as the definition. 20be503cae 2010-11-24 kinaba: You need to wrap it up in a function (like the foo() in the above example). 20be503cae 2010-11-24 kinaba: </pre> 8caee17864 2010-11-24 kinaba: )) 8caee17864 2010-11-24 kinaba: ) 20be503cae 2010-11-24 kinaba: )) 20be503cae 2010-11-24 kinaba: 20be503cae 2010-11-24 kinaba: 20be503cae 2010-11-24 kinaba: $(SECTION Built-in Primitives, $(SECBODY 20be503cae 2010-11-24 kinaba: <p> 20be503cae 2010-11-24 kinaba: 組み込み関数・変数の一覧。 20be503cae 2010-11-24 kinaba: </p> 20be503cae 2010-11-24 kinaba: $(DDOC_MEMBERS 20be503cae 2010-11-24 kinaba: 20be503cae 2010-11-24 kinaba: $(SECTION テーブル操作, $(SECBODY 20be503cae 2010-11-24 kinaba: $(TABLE 20be503cae 2010-11-24 kinaba: $(TR $(TH {}) $(TD ()) $(TD 空のテーブルを作る)) 20be503cae 2010-11-24 kinaba: $(TR $(TH .) $(TD (t, s)) $(TD テーブル t の名前 s のフィールドの値を取得。なければ <tt>undefined</tt>)) 20be503cae 2010-11-24 kinaba: $(TR $(TH .?) $(TD (t, s)) $(TD テーブル t に名前 s のフィールドがあれば 1、なければ 0)) 20be503cae 2010-11-24 kinaba: $(TR $(TH .=) $(TD (t, s, v)) $(TD テーブル t を親に持ち、名前 s のフィールドに v が入ったテーブルを作る)) 20be503cae 2010-11-24 kinaba: ) 20be503cae 2010-11-24 kinaba: )) 20be503cae 2010-11-24 kinaba: <br /> 20be503cae 2010-11-24 kinaba: 20be503cae 2010-11-24 kinaba: $(SECTION 制御フロー, $(SECBODY 20be503cae 2010-11-24 kinaba: $(TABLE 20be503cae 2010-11-24 kinaba: $(TR $(TH if) $(TD (n, ft, fe)) $(TD n が非 0 なら <tt>ft()</t>、0 なら <tt>fe()</tt> を実行)) 20be503cae 2010-11-24 kinaba: ) 20be503cae 2010-11-24 kinaba: )) 20be503cae 2010-11-24 kinaba: <br /> 20be503cae 2010-11-24 kinaba: 20be503cae 2010-11-24 kinaba: $(SECTION 演算, $(SECBODY 20be503cae 2010-11-24 kinaba: $(TABLE 20be503cae 2010-11-24 kinaba: $(TR $(TH +) $(TD (n, m)) $(TD 整数 n と整数 m を足して返す)) 20be503cae 2010-11-24 kinaba: $(TR $(TH -) $(TD (n, m)) $(TD 整数の引き算)) 20be503cae 2010-11-24 kinaba: $(TR $(TH *) $(TD (n, m)) $(TD 整数の掛け算)) 20be503cae 2010-11-24 kinaba: $(TR $(TH /) $(TD (n, m)) $(TD 整数の割り算)) 20be503cae 2010-11-24 kinaba: $(TR $(TH %) $(TD (n, m)) $(TD 整数の剰余)) 20be503cae 2010-11-24 kinaba: $(TR $(TH &&) $(TD (n, m)) $(TD 整数 n と m が両方非 0 なら 1、それ以外では 0)) 20be503cae 2010-11-24 kinaba: $(TR $(TH ||) $(TD (n, m)) $(TD 整数 n と m がどちらか非 0 なら 1、それ以外では 0)) 20be503cae 2010-11-24 kinaba: $(TR $(TH ~) $(TD (a, b)) $(TD a と b を文字列化して結合)) 20be503cae 2010-11-24 kinaba: $(TR $(TH <) $(TD (a, b)) $(TD a と b を比較)) 20be503cae 2010-11-24 kinaba: $(TR $(TH <=) $(TD (a, b)) $(TD a と b を比較)) 20be503cae 2010-11-24 kinaba: $(TR $(TH >) $(TD (a, b)) $(TD a と b を比較)) 20be503cae 2010-11-24 kinaba: $(TR $(TH >=) $(TD (a, b)) $(TD a と b を比較)) 20be503cae 2010-11-24 kinaba: $(TR $(TH ==) $(TD (a, b)) $(TD a と b を比較)) 20be503cae 2010-11-24 kinaba: $(TR $(TH !=) $(TD (a, b)) $(TD a と b を比較)) 20be503cae 2010-11-24 kinaba: ) 20be503cae 2010-11-24 kinaba: <p> 20be503cae 2010-11-24 kinaba: 注意点として、作者の趣味の問題で、<tt>&&</tt> と <tt>||</tt> は short-circuit 評価をしません。 20be503cae 2010-11-24 kinaba: 整数演算の種類が少ないのは、D 言語の std.bigint がビット演算などをサポートしてないためです。 20be503cae 2010-11-24 kinaba: 文字列が結合しかできないのは、単に手抜きです。 20be503cae 2010-11-24 kinaba: </p> 20be503cae 2010-11-24 kinaba: )) 20be503cae 2010-11-24 kinaba: 20be503cae 2010-11-24 kinaba: $(SECTION 外部とのやりとり, $(SECBODY 20be503cae 2010-11-24 kinaba: $(TABLE 20be503cae 2010-11-24 kinaba: $(TR $(TH print) $(TD (a)) $(TD a を文字列化標準出力に改行付きで表示)) 20be503cae 2010-11-24 kinaba: $(TR $(TH argv) $(TD ) $(TD スクリプトに渡された引数文字列のconsリスト)) 20be503cae 2010-11-24 kinaba: ) 20be503cae 2010-11-24 kinaba: )) 20be503cae 2010-11-24 kinaba: <br /> 20be503cae 2010-11-24 kinaba: 20be503cae 2010-11-24 kinaba: $(SECTION データ型判定, $(SECBODY 20be503cae 2010-11-24 kinaba: $(TABLE 20be503cae 2010-11-24 kinaba: $(TR $(TH _isint) $(TD (a)) $(TD a が整数なら 1、でなければ 0)) 20be503cae 2010-11-24 kinaba: $(TR $(TH _isstr) $(TD (a)) $(TD a が文字列なら 1、でなければ 0)) 20be503cae 2010-11-24 kinaba: $(TR $(TH _isfun) $(TD (a)) $(TD a が関数なら 1、でなければ 0)) 20be503cae 2010-11-24 kinaba: $(TR $(TH _istable) $(TD (a)) $(TD a がテーブルなら 1、でなければ 0)) 20be503cae 2010-11-24 kinaba: $(TR $(TH _isundefined) $(TD (a)) $(TD a が未定義値なら 1、でなければ 0)) 20be503cae 2010-11-24 kinaba: ) 20be503cae 2010-11-24 kinaba: )) 20be503cae 2010-11-24 kinaba: ) 20be503cae 2010-11-24 kinaba: )) 20be503cae 2010-11-24 kinaba: 20be503cae 2010-11-24 kinaba: ) 20be503cae 2010-11-24 kinaba: Macros: 20be503cae 2010-11-24 kinaba: TITLE=Polemy Reference Manual 20be503cae 2010-11-24 kinaba: DOCFILENAME=index.html 20be503cae 2010-11-24 kinaba: SECTION=$(DDOC_DECL $(DDOC_PSYMBOL $1)) $(DDOC_DECL_DD $2) 20be503cae 2010-11-24 kinaba: SECBODY=$0