8caee17864 2010-11-24 kinaba: 8caee17864 2010-11-24 kinaba: <html><head> 8caee17864 2010-11-24 kinaba: <meta http-equiv="content-type" content="text/html; charset=utf-8"> 8caee17864 2010-11-24 kinaba: <meta content="text/javascript" http-equiv="content-script-type"> 8caee17864 2010-11-24 kinaba: <title>Polemy Reference Manual</title> 8caee17864 2010-11-24 kinaba: <link rel="stylesheet" type="text/css" href="candydoc/style.css"> 8caee17864 2010-11-24 kinaba: <!--[if lt IE 7]><link rel="stylesheet" type="text/css" href="candydoc/ie56hack.css"><![endif]--> 8caee17864 2010-11-24 kinaba: <script language="JavaScript" src="candydoc/util.js" type="text/javascript"></script> 8caee17864 2010-11-24 kinaba: <script language="JavaScript" src="candydoc/tree.js" type="text/javascript"></script> 8caee17864 2010-11-24 kinaba: <script language="JavaScript" src="candydoc/explorer.js" type="text/javascript"></script> 8caee17864 2010-11-24 kinaba: </head><body> 8caee17864 2010-11-24 kinaba: <div id="tabarea"></div><div id="explorerclient"></div> 8caee17864 2010-11-24 kinaba: <div id="content"><script>explorer.initialize("Polemy Reference Manual");</script> 8caee17864 2010-11-24 kinaba: <table class="content"> 8caee17864 2010-11-24 kinaba: <tr><td id="docbody"><h1>Polemy Reference Manual</h1><!-- Generated by Ddoc from index.dd --> 8caee17864 2010-11-24 kinaba: 8caee17864 2010-11-24 kinaba: <b>Authors:</b><br> 8caee17864 2010-11-24 kinaba: k.inaba<br><br> 8caee17864 2010-11-24 kinaba: <b>License:</b><br> 8caee17864 2010-11-24 kinaba: NYSL 0.9982 (http://www.kmonos.net/nysl/)<br><br> 8caee17864 2010-11-24 kinaba: 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: あとついでに、左のサイドバーの "Package" タブをクリックすると実装のソースのドキュメントが読めます。 8caee17864 2010-11-24 kinaba: </p> 8caee17864 2010-11-24 kinaba: 8caee17864 2010-11-24 kinaba: 8caee17864 2010-11-24 kinaba: <script>explorer.outline.incSymbolLevel();</script> 8caee17864 2010-11-24 kinaba: <dl> 8caee17864 2010-11-24 kinaba: <script>explorer.outline.writeEnabled = true;</script> 8caee17864 2010-11-24 kinaba: <dt><span class="decl"> 8caee17864 2010-11-24 kinaba: <span class="currsymbol">Syntax</span> 8caee17864 2010-11-24 kinaba: <script>explorer.outline.addDecl('Syntax');</script> 8caee17864 2010-11-24 kinaba: 8caee17864 2010-11-24 kinaba: </span></dt> 8caee17864 2010-11-24 kinaba: <script>explorer.outline.writeEnabled = false;</script> 8caee17864 2010-11-24 kinaba: 8caee17864 2010-11-24 kinaba: <dd><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: 8caee17864 2010-11-24 kinaba: 8caee17864 2010-11-24 kinaba: <script>explorer.outline.incSymbolLevel();</script> 8caee17864 2010-11-24 kinaba: <dl> 8caee17864 2010-11-24 kinaba: <script>explorer.outline.writeEnabled = true;</script> 8caee17864 2010-11-24 kinaba: <dt><span class="decl"> 8caee17864 2010-11-24 kinaba: <span class="currsymbol">文字コード</span> 8caee17864 2010-11-24 kinaba: <script>explorer.outline.addDecl('文字コード');</script> 8caee17864 2010-11-24 kinaba: 8caee17864 2010-11-24 kinaba: </span></dt> 8caee17864 2010-11-24 kinaba: <script>explorer.outline.writeEnabled = false;</script> 8caee17864 2010-11-24 kinaba: 8caee17864 2010-11-24 kinaba: <dd><p> 8caee17864 2010-11-24 kinaba: UTF-8 のみ対応です。 8caee17864 2010-11-24 kinaba: </p> 8caee17864 2010-11-24 kinaba: </dd> 8caee17864 2010-11-24 kinaba: 8caee17864 2010-11-24 kinaba: 8caee17864 2010-11-24 kinaba: <script>explorer.outline.writeEnabled = true;</script> 8caee17864 2010-11-24 kinaba: <dt><span class="decl"> 8caee17864 2010-11-24 kinaba: <span class="currsymbol">コメント</span> 8caee17864 2010-11-24 kinaba: <script>explorer.outline.addDecl('コメント');</script> 8caee17864 2010-11-24 kinaba: 8caee17864 2010-11-24 kinaba: </span></dt> 8caee17864 2010-11-24 kinaba: <script>explorer.outline.writeEnabled = false;</script> 8caee17864 2010-11-24 kinaba: 8caee17864 2010-11-24 kinaba: <dd><p> 8caee17864 2010-11-24 kinaba: 行コメントは <tt>#</tt> から改行までです。 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: </dd> 8caee17864 2010-11-24 kinaba: 8caee17864 2010-11-24 kinaba: 8caee17864 2010-11-24 kinaba: <script>explorer.outline.writeEnabled = true;</script> 8caee17864 2010-11-24 kinaba: <dt><span class="decl"> 8caee17864 2010-11-24 kinaba: <span class="currsymbol">BNF</span> 8caee17864 2010-11-24 kinaba: <script>explorer.outline.addDecl('BNF');</script> 8caee17864 2010-11-24 kinaba: 8caee17864 2010-11-24 kinaba: </span></dt> 8caee17864 2010-11-24 kinaba: <script>explorer.outline.writeEnabled = false;</script> 8caee17864 2010-11-24 kinaba: 8caee17864 2010-11-24 kinaba: <dd><pre> 8caee17864 2010-11-24 kinaba: ID ::= 適当に識別子っぽい文字列 8caee17864 2010-11-24 kinaba: LAYER ::= "@" ID 8caee17864 2010-11-24 kinaba: 8caee17864 2010-11-24 kinaba: E ::= 8caee17864 2010-11-24 kinaba: <font color=green># 変数宣言</font> 8caee17864 2010-11-24 kinaba: | ("var"|"let"|"def"|LAYER) ID "=" E (";"|"in") E 8caee17864 2010-11-24 kinaba: | ("var"|"let"|"def"|LAYER) ID "(" PARAMS ")" "{" E "}" (";"|"in") E 8caee17864 2010-11-24 kinaba: | ("var"|"let"|"def"|LAYER) ID "=" E 8caee17864 2010-11-24 kinaba: | ("var"|"let"|"def"|LAYER) ID "(" PARAMS ")" "{" E "}" 8caee17864 2010-11-24 kinaba: 8caee17864 2010-11-24 kinaba: <font color=green># リテラル</font> 8caee17864 2010-11-24 kinaba: | INTEGER <font color=green># 非負整数</font> 8caee17864 2010-11-24 kinaba: | STRING <font color=green># "" でくくった文字列。\" と \\ は使える</font> 8caee17864 2010-11-24 kinaba: | "{" ENTRYS "}" <font color=green># テーブル</font> 8caee17864 2010-11-24 kinaba: | "fun" "(" PARAMS ")" "{" E "}" <font color=green># 無名関数</font> 8caee17864 2010-11-24 kinaba: | "λ" "(" PARAMS ")" "{" E "}" <font color=green># 無名関数</font> 8caee17864 2010-11-24 kinaba: 8caee17864 2010-11-24 kinaba: <font color=green># 関数呼び出し</font> 8caee17864 2010-11-24 kinaba: | E "(" ARGS")" 8caee17864 2010-11-24 kinaba: 8caee17864 2010-11-24 kinaba: where ARGS ::= E "," ... "," E 8caee17864 2010-11-24 kinaba: PARAMS ::= (ID|LAYER)+ "," ... "," (ID|LAYER)+ 8caee17864 2010-11-24 kinaba: ENTRYS ::= ID ":" E "," ... "," ID ":" E 8caee17864 2010-11-24 kinaba: 8caee17864 2010-11-24 kinaba: <font color=green># 演算子など</font> 8caee17864 2010-11-24 kinaba: | "(" E ")" <font color=green># ただの括弧</font> 8caee17864 2010-11-24 kinaba: | E BINOP E <font color=green># 二項演算子いろいろ</font> 8caee17864 2010-11-24 kinaba: | E "." ID <font color=green># テーブルのフィールドアクセス</font> 8caee17864 2010-11-24 kinaba: | E ".?" ID <font color=green># テーブルにフィールドがあるか否か</font> 8caee17864 2010-11-24 kinaba: | E "{" ENTRYS "}" <font color=green># テーブル拡張</font> 3ae09b8cbf 2010-11-24 kinaba: | "if" E ("then"|":"|"then" ":") E 3ae09b8cbf 2010-11-24 kinaba: | "if" E ("then"|":"|"then" ":") E "else" ":"? E 8caee17864 2010-11-24 kinaba: 8caee17864 2010-11-24 kinaba: <font color=green># パターンマッチ</font> 3ae09b8cbf 2010-11-24 kinaba: | "case" E ("when" PATTERN ":" E )* 8caee17864 2010-11-24 kinaba: 8caee17864 2010-11-24 kinaba: where PATTERN ::= 式がだいたいなんでも書ける気がする 8caee17864 2010-11-24 kinaba: 8caee17864 2010-11-24 kinaba: <font color=green># レイヤ指定実行</font> 8caee17864 2010-11-24 kinaba: | LAYER "(" E ")" 8caee17864 2010-11-24 kinaba: </pre> 8caee17864 2010-11-24 kinaba: </dd> 8caee17864 2010-11-24 kinaba: 8caee17864 2010-11-24 kinaba: 8caee17864 2010-11-24 kinaba: <script>explorer.outline.writeEnabled = true;</script> 8caee17864 2010-11-24 kinaba: <dt><span class="decl"> 8caee17864 2010-11-24 kinaba: <span class="currsymbol">糖衣構文</span> 8caee17864 2010-11-24 kinaba: <script>explorer.outline.addDecl('糖衣構文');</script> 8caee17864 2010-11-24 kinaba: 8caee17864 2010-11-24 kinaba: </span></dt> 8caee17864 2010-11-24 kinaba: <script>explorer.outline.writeEnabled = false;</script> 8caee17864 2010-11-24 kinaba: 8caee17864 2010-11-24 kinaba: <dd><p> 8caee17864 2010-11-24 kinaba: 演算子というものはありません。内部的には全て関数呼び出し構文に書き換えられています。<tt>if</tt> もです。 8caee17864 2010-11-24 kinaba: <br/> 8caee17864 2010-11-24 kinaba: パターンマッチも全部 <tt>if</tt> と <tt>==</tt> と <tt>&&</tt> と 8caee17864 2010-11-24 kinaba: <tt>.</tt> と <tt>.?</tt> を使った関数呼び出し式に書き換えられていますが、 8caee17864 2010-11-24 kinaba: 規則の詳細を説明するのが面倒なので適当に想像して下さい。 8caee17864 2010-11-24 kinaba: 他の書き換えはこんな感じです。 8caee17864 2010-11-24 kinaba: </p> 8caee17864 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) { ... } 8caee17864 2010-11-24 kinaba: </pre> 8caee17864 2010-11-24 kinaba: <p> 8caee17864 2010-11-24 kinaba: 変数宣言に色々ありますが、<tt>let</tt> と <tt>var</tt> と <tt>def</tt> は同じ扱いで、 8caee17864 2010-11-24 kinaba: <tt>in</tt> と <tt>;</tt> は同じ扱いです。つまり 8caee17864 2010-11-24 kinaba: </p> 8caee17864 2010-11-24 kinaba: <pre> 8caee17864 2010-11-24 kinaba: let x = E in E 8caee17864 2010-11-24 kinaba: var x = E in E 8caee17864 2010-11-24 kinaba: def x = E in E 8caee17864 2010-11-24 kinaba: let x = E ; E 8caee17864 2010-11-24 kinaba: var x = E ; E 8caee17864 2010-11-24 kinaba: def x = E ; E 8caee17864 2010-11-24 kinaba: </pre> 8caee17864 2010-11-24 kinaba: <p> 8caee17864 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> も微妙にコロンがあったりなかったりバリエーションがありますが好みで使います。 8caee17864 2010-11-24 kinaba: </p> 8caee17864 2010-11-24 kinaba: <p> 8caee17864 2010-11-24 kinaba: 関数を宣言するときは、<tt>fun</tt> や <tt>λ</tt> を省略できます。 8caee17864 2010-11-24 kinaba: 以下の書き換えが行われます。 8caee17864 2010-11-24 kinaba: </p> 8caee17864 2010-11-24 kinaba: <pre> 8caee17864 2010-11-24 kinaba: def f( ARGS ) { E }; E ⇒ def f = fun(ARGS){E}; E 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: <pre> 8caee17864 2010-11-24 kinaba: fun () { E; E; E } ⇒ fun () { let _ = E in let _ = E in E } 8caee17864 2010-11-24 kinaba: fun () { var x = 100 } ⇒ fun () { var x = 100; x } 8caee17864 2010-11-24 kinaba: fun () { var x = 100; } ⇒ fun () { var x = 100; x } 8caee17864 2010-11-24 kinaba: fun () { } ⇒ fun () { "(empty function body)" } 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: </dd> 8caee17864 2010-11-24 kinaba: 8caee17864 2010-11-24 kinaba: 8caee17864 2010-11-24 kinaba: <script>explorer.outline.writeEnabled = true;</script> 8caee17864 2010-11-24 kinaba: <dt><span class="decl"> 8caee17864 2010-11-24 kinaba: <span class="currsymbol">変数のスコープ規則</span> 8caee17864 2010-11-24 kinaba: <script>explorer.outline.addDecl('変数のスコープ規則');</script> 8caee17864 2010-11-24 kinaba: 8caee17864 2010-11-24 kinaba: </span></dt> 8caee17864 2010-11-24 kinaba: <script>explorer.outline.writeEnabled = false;</script> 8caee17864 2010-11-24 kinaba: 8caee17864 2010-11-24 kinaba: <dd><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 <font color=green># 42</font> 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) <font color=green># 3628800</font> 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() <font color=green># 2!!</font> 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: で他レイヤに重ね書きするためであります。 8caee17864 2010-11-24 kinaba: </p> 8caee17864 2010-11-24 kinaba: </dd> 8caee17864 2010-11-24 kinaba: </dl> 8caee17864 2010-11-24 kinaba: <script>explorer.outline.decSymbolLevel();</script> 8caee17864 2010-11-24 kinaba: 8caee17864 2010-11-24 kinaba: 8caee17864 2010-11-24 kinaba: </dd> 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: <script>explorer.outline.writeEnabled = true;</script> 8caee17864 2010-11-24 kinaba: <dt><span class="decl"> 8caee17864 2010-11-24 kinaba: <span class="currsymbol">Basic Features</span> 8caee17864 2010-11-24 kinaba: <script>explorer.outline.addDecl('Basic Features');</script> 8caee17864 2010-11-24 kinaba: 8caee17864 2010-11-24 kinaba: </span></dt> 8caee17864 2010-11-24 kinaba: <script>explorer.outline.writeEnabled = false;</script> 8caee17864 2010-11-24 kinaba: 8caee17864 2010-11-24 kinaba: <dd><p> 8caee17864 2010-11-24 kinaba: 特に特徴的でもない部分を簡単にまとめ。 8caee17864 2010-11-24 kinaba: </p> 8caee17864 2010-11-24 kinaba: <ul> 8caee17864 2010-11-24 kinaba: <li>静的型システムはありません。</li> 8caee17864 2010-11-24 kinaba: <li>"ほぼ" 純粋関数型言語です。変数やテーブルのフィールドの破壊的な書き換えはできません。<br/> 8caee17864 2010-11-24 kinaba: ただし、組み込み関数(<tt>print</tt>)と、変数のスコープ規則のマジカルな片隅に副作用があります。</li> 8caee17864 2010-11-24 kinaba: </ul> 8caee17864 2010-11-24 kinaba: <p> 8caee17864 2010-11-24 kinaba: 静的型システムがないのは意図的ですが、破壊的代入がないのは、単に実装がめんどかっただけなので、 8caee17864 2010-11-24 kinaba: 今後何か増えるかもしれません。増えないかもしれません。 8caee17864 2010-11-24 kinaba: </p> 8caee17864 2010-11-24 kinaba: 8caee17864 2010-11-24 kinaba: <script>explorer.outline.incSymbolLevel();</script> 8caee17864 2010-11-24 kinaba: <dl> 8caee17864 2010-11-24 kinaba: <script>explorer.outline.writeEnabled = true;</script> 8caee17864 2010-11-24 kinaba: <dt><span class="decl"> 8caee17864 2010-11-24 kinaba: <span class="currsymbol">データ型</span> 8caee17864 2010-11-24 kinaba: <script>explorer.outline.addDecl('データ型');</script> 8caee17864 2010-11-24 kinaba: 8caee17864 2010-11-24 kinaba: </span></dt> 8caee17864 2010-11-24 kinaba: <script>explorer.outline.writeEnabled = false;</script> 8caee17864 2010-11-24 kinaba: 8caee17864 2010-11-24 kinaba: <dd><p> 8caee17864 2010-11-24 kinaba: 以下のデータ型があります。 8caee17864 2010-11-24 kinaba: </p> 8caee17864 2010-11-24 kinaba: <ul> 8caee17864 2010-11-24 kinaba: <li>整数: <tt>0</tt>, <tt>123</tt>, <tt>456666666666666666666666666666666666666789</tt>, ...</li> 8caee17864 2010-11-24 kinaba: <li>文字列: <tt>"hello, world!"</tt>, ...</li> 8caee17864 2010-11-24 kinaba: <li>関数: <tt>fun(x){x+1}</tt></li> 8caee17864 2010-11-24 kinaba: <li>テーブル: <tt>{car: 1, cdr: {car: 2, cdr: {}}}</tt></li> c0158c9281 2010-11-24 kinaba: <li>未定義値: (undefined。特殊なケースで作られます)</li> 8caee17864 2010-11-24 kinaba: </ul> 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: フィールドの書き換えがないので、これは特に意味ないかもしれない…。 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> 8caee17864 2010-11-24 kinaba: </dd> 8caee17864 2010-11-24 kinaba: 8caee17864 2010-11-24 kinaba: <script>explorer.outline.writeEnabled = true;</script> 8caee17864 2010-11-24 kinaba: <dt><span class="decl"> 8caee17864 2010-11-24 kinaba: <span class="currsymbol">パターンマッチ</span> 8caee17864 2010-11-24 kinaba: <script>explorer.outline.addDecl('パターンマッチ');</script> 8caee17864 2010-11-24 kinaba: 8caee17864 2010-11-24 kinaba: </span></dt> 8caee17864 2010-11-24 kinaba: <script>explorer.outline.writeEnabled = false;</script> 8caee17864 2010-11-24 kinaba: 8caee17864 2010-11-24 kinaba: <dd><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 ::= "_" <font color=green># ワイルドカード</font> 8caee17864 2010-11-24 kinaba: | ID <font color=green># 変数パターン</font> 8caee17864 2010-11-24 kinaba: | "{" ID ":" PAT "," ... "," ID : PAT "}" <font color=green># テーブルパターン</font> 8caee17864 2010-11-24 kinaba: | E <font color=green># 値パターン</font> 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}: ... <font color=green># これは {val:123} と同じ</font> 3ae09b8cbf 2010-11-24 kinaba: when {val: x}: ... <font color=green># これは任意の foo.?val なら常にマッチ</font> 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> 8caee17864 2010-11-24 kinaba: </dd> 8caee17864 2010-11-24 kinaba: </dl> 8caee17864 2010-11-24 kinaba: <script>explorer.outline.decSymbolLevel();</script> 8caee17864 2010-11-24 kinaba: 8caee17864 2010-11-24 kinaba: 8caee17864 2010-11-24 kinaba: </dd> 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: 8caee17864 2010-11-24 kinaba: <script>explorer.outline.writeEnabled = true;</script> 8caee17864 2010-11-24 kinaba: <dt><span class="decl"> 8caee17864 2010-11-24 kinaba: <span class="currsymbol">Layers</span> 8caee17864 2010-11-24 kinaba: <script>explorer.outline.addDecl('Layers');</script> 8caee17864 2010-11-24 kinaba: 8caee17864 2010-11-24 kinaba: </span></dt> 8caee17864 2010-11-24 kinaba: <script>explorer.outline.writeEnabled = false;</script> 8caee17864 2010-11-24 kinaba: 8caee17864 2010-11-24 kinaba: <dd><pre> 8caee17864 2010-11-24 kinaba: [Layers :: Overview] 8caee17864 2010-11-24 kinaba: 8caee17864 2010-11-24 kinaba: Polemy's runtime environment has many "layer"s. 8caee17864 2010-11-24 kinaba: Usual execution run in the @value layer. 8caee17864 2010-11-24 kinaba: 8caee17864 2010-11-24 kinaba: >> 1 + 2 8caee17864 2010-11-24 kinaba: 3 8caee17864 2010-11-24 kinaba: >> @value( 1 + 2 ) 8caee17864 2010-11-24 kinaba: 3 8caee17864 2010-11-24 kinaba: 8caee17864 2010-11-24 kinaba: Here you can see that @LayerName( Expression ) executes the inner Expression in 8caee17864 2010-11-24 kinaba: the @LayerName layer. Other than @value, one other predefined layer exists: @macro. 8caee17864 2010-11-24 kinaba: 8caee17864 2010-11-24 kinaba: >> @macro( 1+2 ) 8caee17864 2010-11-24 kinaba: {pos@value:{lineno@value:3, column@value:9, filename@value:<REPL>}, 8caee17864 2010-11-24 kinaba: is@value:app, 8caee17864 2010-11-24 kinaba: args@value:{car@value:{pos@value:{lineno@value:3, column@value:9, filename@value:<REPL>}, 8caee17864 2010-11-24 kinaba: is@value:int, 8caee17864 2010-11-24 kinaba: data@value:1}, 8caee17864 2010-11-24 kinaba: cdr@value:{ 8caee17864 2010-11-24 kinaba: car@value:{pos@value:{lineno@value:3, column@value:11, filename@value:<REPL>}, 8caee17864 2010-11-24 kinaba: is@value:int, 8caee17864 2010-11-24 kinaba: data@value:2}, 8caee17864 2010-11-24 kinaba: cdr@value:{}}}, 8caee17864 2010-11-24 kinaba: fun@value:{pos@value:{lineno@value:3, column@value:10, filename@value:<REPL>}, 8caee17864 2010-11-24 kinaba: is@value:var, 8caee17864 2010-11-24 kinaba: name@value:+}} 8caee17864 2010-11-24 kinaba: 8caee17864 2010-11-24 kinaba: (Sorry, this pretty printing is not available on the actual interpreter...) 8caee17864 2010-11-24 kinaba: This evaluates the expression 1+2 in the @macro layer. In this layer, the meaning of 8caee17864 2010-11-24 kinaba: the program is its abstract syntax tree. 8caee17864 2010-11-24 kinaba: 8caee17864 2010-11-24 kinaba: You can interleave layers. 8caee17864 2010-11-24 kinaba: The root node of the abstract syntax tree is function "app"lication. 8caee17864 2010-11-24 kinaba: 8caee17864 2010-11-24 kinaba: >> @value(@macro( 1+2 ).is) 8caee17864 2010-11-24 kinaba: app 8caee17864 2010-11-24 kinaba: 8caee17864 2010-11-24 kinaba: 8caee17864 2010-11-24 kinaba: 8caee17864 2010-11-24 kinaba: [Layers :: Defining a new layer] 8caee17864 2010-11-24 kinaba: 8caee17864 2010-11-24 kinaba: To define a new layer, you should first tell how to "lift" existing values two the new layer. 8caee17864 2010-11-24 kinaba: Let us define the "@type" layer, where the meaning of programs is their static type. 8caee17864 2010-11-24 kinaba: 8caee17864 2010-11-24 kinaba: >> @@type = fun(x) { 8caee17864 2010-11-24 kinaba: >> if( _isint(x) ) { "int" } else { 8caee17864 2010-11-24 kinaba: >> if( _isfun(x) ) { x } else { "unknown" } } 8caee17864 2010-11-24 kinaba: >> } 8caee17864 2010-11-24 kinaba: (Note: polemy REPL may warn some exception here but please ignore) 8caee17864 2010-11-24 kinaba: 8caee17864 2010-11-24 kinaba: For simplicity, I here deal only with integers. 8caee17864 2010-11-24 kinaba: _isint is a primitive function of Polemy that checks the dynamic type of a value. 8caee17864 2010-11-24 kinaba: For function, leaving it untouched works well for almost all layers. 8caee17864 2010-11-24 kinaba: 8caee17864 2010-11-24 kinaba: >> @type( 1 ) 8caee17864 2010-11-24 kinaba: int 8caee17864 2010-11-24 kinaba: >> @type( 2 ) 8caee17864 2010-11-24 kinaba: int 8caee17864 2010-11-24 kinaba: >> @type( "foo" ) 8caee17864 2010-11-24 kinaba: unknown 8caee17864 2010-11-24 kinaba: 8caee17864 2010-11-24 kinaba: Fine! Let's try to type 1+2. 8caee17864 2010-11-24 kinaba: 8caee17864 2010-11-24 kinaba: >> @type( 1 + 2 ) 8caee17864 2010-11-24 kinaba: ...\value.d(119): [<REPL>:6:8] only @value layer can call native function 8caee17864 2010-11-24 kinaba: 8caee17864 2010-11-24 kinaba: Note that the behavior of this program is 8caee17864 2010-11-24 kinaba: - run 1+2 in the @type layer 8caee17864 2010-11-24 kinaba: and NOT 8caee17864 2010-11-24 kinaba: - run 1+2 in @value and obtain 3 and run 3 in the @type. 8caee17864 2010-11-24 kinaba: The problem is, the variable "+" is defined only in the @value layer. 8caee17864 2010-11-24 kinaba: To carry out computation in the @type layer. We need to define it also 8caee17864 2010-11-24 kinaba: in the @type layer. 8caee17864 2010-11-24 kinaba: 8caee17864 2010-11-24 kinaba: To define some variable in a specific layer, use @LayerName in place of 8caee17864 2010-11-24 kinaba: (let|var|def)s. 8caee17864 2010-11-24 kinaba: 8caee17864 2010-11-24 kinaba: >> let x = 2 8caee17864 2010-11-24 kinaba: >> @value x = 2 8caee17864 2010-11-24 kinaba: >> @type x = "int" 8caee17864 2010-11-24 kinaba: >> @hoge x = "fuga" 8caee17864 2010-11-24 kinaba: 8caee17864 2010-11-24 kinaba: For "+", do it like this. 8caee17864 2010-11-24 kinaba: 8caee17864 2010-11-24 kinaba: >> @type "+" = fun(x,y) {@value( 8caee17864 2010-11-24 kinaba: >> if( @type(x)=="int" && @type(y)=="int" ) { "int" } else { "typeerror" } 8caee17864 2010-11-24 kinaba: >> )} 8caee17864 2010-11-24 kinaba: polemy.value.native!(IntValue,IntValue,IntValue).native.__anonclass24 8caee17864 2010-11-24 kinaba: 8caee17864 2010-11-24 kinaba: It is just computing the return type from the input type. 8caee17864 2010-11-24 kinaba: Not here that the intended "meaning" of if-then-else is the runtime-branching, 8caee17864 2010-11-24 kinaba: and the meaning of "==" is the value-comparison. These are the @value layer 8caee17864 2010-11-24 kinaba: behavior. So we have defined the function body inside @value layer. 8caee17864 2010-11-24 kinaba: But when we refer the variables x and y, we need its @type layer meaning. 8caee17864 2010-11-24 kinaba: Hence we use @type() there. 8caee17864 2010-11-24 kinaba: 8caee17864 2010-11-24 kinaba: Now we get it. 8caee17864 2010-11-24 kinaba: 8caee17864 2010-11-24 kinaba: >> @type( 1 + 2 ) 8caee17864 2010-11-24 kinaba: int 8caee17864 2010-11-24 kinaba: 8caee17864 2010-11-24 kinaba: Well, but do we have to define the @type layer meaning for every variables??? 8caee17864 2010-11-24 kinaba: No. After you defined @type "+", you'll automatically get the following: 8caee17864 2010-11-24 kinaba: 8caee17864 2010-11-24 kinaba: >> def double(x) { x + x } 8caee17864 2010-11-24 kinaba: (function:17e4740:1789720) 8caee17864 2010-11-24 kinaba: 8caee17864 2010-11-24 kinaba: >> @type( double(123) ) 8caee17864 2010-11-24 kinaba: int 8caee17864 2010-11-24 kinaba: 8caee17864 2010-11-24 kinaba: Every user-defined functions are automatically "lift"ed to the appropriate layer. 8caee17864 2010-11-24 kinaba: Only primitive functions like "+" requires @yourNewLayer annotation. 8caee17864 2010-11-24 kinaba: 8caee17864 2010-11-24 kinaba: 8caee17864 2010-11-24 kinaba: 8caee17864 2010-11-24 kinaba: [Layers :: neutral-layer] 8caee17864 2010-11-24 kinaba: 8caee17864 2010-11-24 kinaba: let|var|def is to define a variable in the "current" layer. 8caee17864 2010-11-24 kinaba: Not necessary to the @value layer. 8caee17864 2010-11-24 kinaba: 8caee17864 2010-11-24 kinaba: >> @value( let x = 1 in @value(x) ) 8caee17864 2010-11-24 kinaba: 1 8caee17864 2010-11-24 kinaba: 8caee17864 2010-11-24 kinaba: >> @macro( let x = 1 in @value(x) ) 8caee17864 2010-11-24 kinaba: polemy.failure.RuntimeException: [<REPL>:14:29] variable x not found 8caee17864 2010-11-24 kinaba: 8caee17864 2010-11-24 kinaba: >> @macro( let x = 1 in @macro(x) ) 8caee17864 2010-11-24 kinaba: {pos@value:{lineno@value:15, ... 8caee17864 2010-11-24 kinaba: 8caee17864 2010-11-24 kinaba: 8caee17864 2010-11-24 kinaba: 8caee17864 2010-11-24 kinaba: [Layers :: Layered-Parameters] 8caee17864 2010-11-24 kinaba: 8caee17864 2010-11-24 kinaba: >> def foo(x @macro @value) { {fst: x, snd: @macro(x)} } 8caee17864 2010-11-24 kinaba: (function:1730360:1789720) 8caee17864 2010-11-24 kinaba: 8caee17864 2010-11-24 kinaba: If you annotate function parameters by @LayerNames, when you invoke the function... 8caee17864 2010-11-24 kinaba: 8caee17864 2010-11-24 kinaba: >> foo(1+2) 8caee17864 2010-11-24 kinaba: {snd@value: {pos@value:{lineno@value:17, column@value:5, filename@value:<REPL>}, 8caee17864 2010-11-24 kinaba: is@value:app, arg@value:{... 8caee17864 2010-11-24 kinaba: /fst@value:3 8caee17864 2010-11-24 kinaba: /} 8caee17864 2010-11-24 kinaba: 8caee17864 2010-11-24 kinaba: its corresponding arguments are evaluated in the layer and passed to it. 8caee17864 2010-11-24 kinaba: If you specify multiple layers, the argument expression is run multiple times. 8caee17864 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: </dd> 8caee17864 2010-11-24 kinaba: 8caee17864 2010-11-24 kinaba: 8caee17864 2010-11-24 kinaba: 8caee17864 2010-11-24 kinaba: <script>explorer.outline.writeEnabled = true;</script> 8caee17864 2010-11-24 kinaba: <dt><span class="decl"> 8caee17864 2010-11-24 kinaba: <span class="currsymbol">Macro Layers</span> 8caee17864 2010-11-24 kinaba: <script>explorer.outline.addDecl('Macro Layers');</script> 8caee17864 2010-11-24 kinaba: 8caee17864 2010-11-24 kinaba: </span></dt> 8caee17864 2010-11-24 kinaba: <script>explorer.outline.writeEnabled = false;</script> 8caee17864 2010-11-24 kinaba: 8caee17864 2010-11-24 kinaba: <dd><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> 8caee17864 2010-11-24 kinaba: 8caee17864 2010-11-24 kinaba: 8caee17864 2010-11-24 kinaba: <script>explorer.outline.incSymbolLevel();</script> 8caee17864 2010-11-24 kinaba: <dl> 8caee17864 2010-11-24 kinaba: <script>explorer.outline.writeEnabled = true;</script> 8caee17864 2010-11-24 kinaba: <dt><span class="decl"> 207cea338a 2010-11-26 kinaba: <span class="currsymbol">概要</span> 207cea338a 2010-11-26 kinaba: <script>explorer.outline.addDecl('概要');</script> 207cea338a 2010-11-26 kinaba: 207cea338a 2010-11-26 kinaba: </span></dt> 207cea338a 2010-11-26 kinaba: <script>explorer.outline.writeEnabled = false;</script> 207cea338a 2010-11-26 kinaba: 207cea338a 2010-11-26 kinaba: <dd><p> 207cea338a 2010-11-26 kinaba: samples/macro.pmy にいくつか使い方サンプルが置いてありますので、詳しくはそちらをどうぞ。 207cea338a 2010-11-26 kinaba: </p> 207cea338a 2010-11-26 kinaba: <pre> 207cea338a 2010-11-26 kinaba: >> @macro( twice(print("Hello")) ) 207cea338a 2010-11-26 kinaba: { 207cea338a 2010-11-26 kinaba: pos: {lineno:1, column:9, filename:<REPL>}, 207cea338a 2010-11-26 kinaba: args: [ { pos: {lineno:1, column:15, filename:<REPL>}, 207cea338a 2010-11-26 kinaba: args: [{pos:{lineno:1, column:21, filename:<REPL>}, 207cea338a 2010-11-26 kinaba: is:Str, 207cea338a 2010-11-26 kinaba: data:Hello}], 207cea338a 2010-11-26 kinaba: is: App, 207cea338a 2010-11-26 kinaba: fun: {pos:{lineno:1, column:15, filename:<REPL>}, is:Var, name:print}} 207cea338a 2010-11-26 kinaba: ], 207cea338a 2010-11-26 kinaba: is: App, 207cea338a 2010-11-26 kinaba: fun: {pos:{lineno:1, column:9, filename:<REPL>}, is:Var, name:twice} 207cea338a 2010-11-26 kinaba: } 207cea338a 2010-11-26 kinaba: </pre> 207cea338a 2010-11-26 kinaba: <p> 207cea338a 2010-11-26 kinaba: 詳細は気にしなくて構いませんが、とにかく、<tt>@macro</tt> レイヤでは、 207cea338a 2010-11-26 kinaba: 基本的には、コードを実行するとそのコードの構文木がでてきます。 207cea338a 2010-11-26 kinaba: この挙動は <tt>@macro</tt> レイヤの変数をセットすることで、カスタマイズできます。 207cea338a 2010-11-26 kinaba: </p> 207cea338a 2010-11-26 kinaba: <pre> 207cea338a 2010-11-26 kinaba: >> @macro twice(x) { x; x } in twice(print("Hello")) 207cea338a 2010-11-26 kinaba: Hello 207cea338a 2010-11-26 kinaba: Hello 207cea338a 2010-11-26 kinaba: Hello 207cea338a 2010-11-26 kinaba: </pre> 207cea338a 2010-11-26 kinaba: <p> 207cea338a 2010-11-26 kinaba: (3回出力されてますが、3個目は <tt>print(x)</tt> の返値は <tt>x</tt> なので、 207cea338a 2010-11-26 kinaba: それがREPLによって印字されているだけです。) 207cea338a 2010-11-26 kinaba: <tt>@macro</tt> レイヤで <tt>in</tt> 以降を実行すると、<tt>print("Hello")</tt> という式を表す構文木が作られ、 207cea338a 2010-11-26 kinaba: それが <tt>twice</tt> 関数に渡されます。<tt>twice</tt> の中身も <tt>@macro</tt> レイヤで実行されるので、 207cea338a 2010-11-26 kinaba: 構文木を作ろうとしますが、変数 <tt>x</tt> には <tt>@macro</tt> レイヤで値が入っているので、 207cea338a 2010-11-26 kinaba: その値を読み取って構文木を作成します。 207cea338a 2010-11-26 kinaba: 結果として、2回 <tt>print("Hello")</tt> する構文木が作られて、 207cea338a 2010-11-26 kinaba: その後で、それが <tt>@value</tt> レイヤで実行されています。 207cea338a 2010-11-26 kinaba: </p> 207cea338a 2010-11-26 kinaba: <p> 207cea338a 2010-11-26 kinaba: 本当にベタに構文木を作るだけなので、変数名の衝突などなどは気にしません。「衛生的でない」マクロです。 207cea338a 2010-11-26 kinaba: </p> 207cea338a 2010-11-26 kinaba: <pre> 207cea338a 2010-11-26 kinaba: @macro LetItBe(x, y) { var <b>it</b> = x; y }; <font color=green># y の中で変数 it が使える</font> 207cea338a 2010-11-26 kinaba: print( LetItBe("myself", "when I find " ~ <b>it</b> ~ " in times of trouble") ); 207cea338a 2010-11-26 kinaba: </pre> 207cea338a 2010-11-26 kinaba: <p> 207cea338a 2010-11-26 kinaba: 変数名に気をつけるには、組み込み関数 <tt>gensym()</tt> を使って頑張って下さい。 207cea338a 2010-11-26 kinaba: </p> 207cea338a 2010-11-26 kinaba: </dd> 207cea338a 2010-11-26 kinaba: 207cea338a 2010-11-26 kinaba: <script>explorer.outline.writeEnabled = true;</script> 207cea338a 2010-11-26 kinaba: <dt><span class="decl"> 207cea338a 2010-11-26 kinaba: <span class="currsymbol">レイヤ切り替え</span> 207cea338a 2010-11-26 kinaba: <script>explorer.outline.addDecl('レイヤ切り替え');</script> c0158c9281 2010-11-24 kinaba: c0158c9281 2010-11-24 kinaba: </span></dt> c0158c9281 2010-11-24 kinaba: <script>explorer.outline.writeEnabled = false;</script> c0158c9281 2010-11-24 kinaba: 207cea338a 2010-11-26 kinaba: <dd><p> 207cea338a 2010-11-26 kinaba: 他のレイヤ同様、<tt>@macro</tt> レイヤを実行中に <tt>@layer( ... )</tt> 構文を使うことで、 207cea338a 2010-11-26 kinaba: 別のレイヤでコードを動かすこともできます。よく使う例は、<tt>@value</tt> 207cea338a 2010-11-26 kinaba: レイヤに移ることで構文木を普通に計算して色々プログラム的にいじる用途です。 207cea338a 2010-11-26 kinaba: </p> 207cea338a 2010-11-26 kinaba: <pre> 207cea338a 2010-11-26 kinaba: @macro reverseArgs(e) {<b>@value</b>( 207cea338a 2010-11-26 kinaba: def rev(xs, acc) { 207cea338a 2010-11-26 kinaba: case xs when {car:x, cdr:xs}: rev(xs, {car:x, cdr:acc}) when {}: acc 207cea338a 2010-11-26 kinaba: }; 207cea338a 2010-11-26 kinaba: case @macro(e) 207cea338a 2010-11-26 kinaba: when {is:"App", fun:f, args:as}: {is:"App", fun:f, args:rev(as,{})} 207cea338a 2010-11-26 kinaba: when e: e 207cea338a 2010-11-26 kinaba: )}; 207cea338a 2010-11-26 kinaba: print( reverseArgs(1-2) ); <font color=green># 2-1 == 1</font> c0158c9281 2010-11-24 kinaba: </pre> c0158c9281 2010-11-24 kinaba: <p> 207cea338a 2010-11-26 kinaba: <tt>reverseArgs</tt> は、関数呼び出しの構文木の、引数の順番を逆転する関数です。 207cea338a 2010-11-26 kinaba: <tt>@macro(e)</tt> によってマクロレイヤにセットされている構文木引数を取り出し、 207cea338a 2010-11-26 kinaba: それを <tt>@value</tt> レイヤによる普通の計算プログラムで操作しています。 207cea338a 2010-11-26 kinaba: 要は、<tt>@macro(...)</tt> はいわゆる「準クオート (quasiquote)」、 207cea338a 2010-11-26 kinaba: <tt>@value(...)</tt> は「逆クオート (unquote)」に近い働きをします。 207cea338a 2010-11-26 kinaba: </p> 207cea338a 2010-11-26 kinaba: <p> 207cea338a 2010-11-26 kinaba: <tt>@layer(...)</tt> だけでなく、関数のレイヤ指定引数なども同様に使うことができるので、 207cea338a 2010-11-26 kinaba: 一部の引数は <tt>@macro</tt>、一部の引数は <tt>@value</tt> レイヤで受け取る関数を書くなど、 207cea338a 2010-11-26 kinaba: さらに色々面白いことが可能です。 207cea338a 2010-11-26 kinaba: </p> 207cea338a 2010-11-26 kinaba: </dd> 207cea338a 2010-11-26 kinaba: 207cea338a 2010-11-26 kinaba: <script>explorer.outline.writeEnabled = true;</script> 207cea338a 2010-11-26 kinaba: <dt><span class="decl"> 207cea338a 2010-11-26 kinaba: <span class="currsymbol">構文木の構造</span> 207cea338a 2010-11-26 kinaba: <script>explorer.outline.addDecl('構文木の構造');</script> 207cea338a 2010-11-26 kinaba: 207cea338a 2010-11-26 kinaba: </span></dt> 207cea338a 2010-11-26 kinaba: <script>explorer.outline.writeEnabled = false;</script> 207cea338a 2010-11-26 kinaba: 207cea338a 2010-11-26 kinaba: <dd><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" } 8caee17864 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 リストになって入ってきます。 207cea338a 2010-11-26 kinaba: 自分で構文木を作る時は、<tt>pos</tt> フィールドだけは省略しても構いません。 c0158c9281 2010-11-24 kinaba: </p> 8caee17864 2010-11-24 kinaba: </dd> 8caee17864 2010-11-24 kinaba: 8caee17864 2010-11-24 kinaba: <script>explorer.outline.writeEnabled = true;</script> 8caee17864 2010-11-24 kinaba: <dt><span class="decl"> 207cea338a 2010-11-26 kinaba: <span class="currsymbol">微妙なところ</span> 207cea338a 2010-11-26 kinaba: <script>explorer.outline.addDecl('微妙なところ');</script> 8caee17864 2010-11-24 kinaba: 8caee17864 2010-11-24 kinaba: </span></dt> 8caee17864 2010-11-24 kinaba: <script>explorer.outline.writeEnabled = false;</script> 8caee17864 2010-11-24 kinaba: 207cea338a 2010-11-26 kinaba: <dd><p> 207cea338a 2010-11-26 kinaba: ここまで、<tt>@macro</tt> が本当にただの1レイヤであるかのように説明してきましたが、 207cea338a 2010-11-26 kinaba: 実はちょっと幾つかのトリックが潜んでいます。 207cea338a 2010-11-26 kinaba: </p> 207cea338a 2010-11-26 kinaba: <pre> 207cea338a 2010-11-26 kinaba: >> @macro twice(x) {x; x} in twice(<b>@value</b>(print("Hello"))) 207cea338a 2010-11-26 kinaba: Hello 207cea338a 2010-11-26 kinaba: Hello 207cea338a 2010-11-26 kinaba: Hello 207cea338a 2010-11-26 kinaba: </pre> 207cea338a 2010-11-26 kinaba: <p> 207cea338a 2010-11-26 kinaba: 先ほどの例に <tt>@value</tt> を増やしたものですが、これでもやはり、Hello 207cea338a 2010-11-26 kinaba: が2回 print されるようになります。 207cea338a 2010-11-26 kinaba: </p> 207cea338a 2010-11-26 kinaba: <pre> 207cea338a 2010-11-26 kinaba: <tt>@macro</tt> レイヤと <tt>(rawmacro)</tt> レイヤという二つが協調して動作しています。 8caee17864 2010-11-24 kinaba: (rawmacro) レイヤの話 8caee17864 2010-11-24 kinaba: 8caee17864 2010-11-24 kinaba: [[limitations]] 8caee17864 2010-11-24 kinaba: 8caee17864 2010-11-24 kinaba: This @macro layer is a very primitive one, and not a perfect macro language. 8caee17864 2010-11-24 kinaba: Two major limitations are seen in the following "it" example. 8caee17864 2010-11-24 kinaba: 8caee17864 2010-11-24 kinaba: >> @macro LetItBe(x, y) { let it = x in y }; 8caee17864 2010-11-24 kinaba: 8caee17864 2010-11-24 kinaba: The variable name is not hygenic, and so without any effort, the syntax tree "y" 8caee17864 2010-11-24 kinaba: can access the outer variable "it". 8caee17864 2010-11-24 kinaba: 8caee17864 2010-11-24 kinaba: >> def foo() { LetItBe( 1+2+3, it*it ) } 8caee17864 2010-11-24 kinaba: >> foo() 8caee17864 2010-11-24 kinaba: 36 8caee17864 2010-11-24 kinaba: 8caee17864 2010-11-24 kinaba: Of course, this is not just a limitation; it can sometimes allow us to write 8caee17864 2010-11-24 kinaba: many interesting macros. 8caee17864 2010-11-24 kinaba: 8caee17864 2010-11-24 kinaba: The other problem is that the macro expansion is only done at function startup. 8caee17864 2010-11-24 kinaba: So 8caee17864 2010-11-24 kinaba: 8caee17864 2010-11-24 kinaba: >> LetItBe( 1+2+3, it*it ) 8caee17864 2010-11-24 kinaba: ...\value.d(173): [<REPL>:24:1] variable LetItBe is not set in layer @value 8caee17864 2010-11-24 kinaba: 8caee17864 2010-11-24 kinaba: you cannot directly use the macro in the same scope as the definition. 8caee17864 2010-11-24 kinaba: You need to wrap it up in a function (like the foo() in the above example). 8caee17864 2010-11-24 kinaba: </pre> 8caee17864 2010-11-24 kinaba: </dd> 8caee17864 2010-11-24 kinaba: </dl> 8caee17864 2010-11-24 kinaba: <script>explorer.outline.decSymbolLevel();</script> 8caee17864 2010-11-24 kinaba: 8caee17864 2010-11-24 kinaba: 8caee17864 2010-11-24 kinaba: </dd> 8caee17864 2010-11-24 kinaba: 8caee17864 2010-11-24 kinaba: 8caee17864 2010-11-24 kinaba: 8caee17864 2010-11-24 kinaba: <script>explorer.outline.writeEnabled = true;</script> 8caee17864 2010-11-24 kinaba: <dt><span class="decl"> 8caee17864 2010-11-24 kinaba: <span class="currsymbol">Built-in Primitives</span> 8caee17864 2010-11-24 kinaba: <script>explorer.outline.addDecl('Built-in Primitives');</script> 8caee17864 2010-11-24 kinaba: 8caee17864 2010-11-24 kinaba: </span></dt> 8caee17864 2010-11-24 kinaba: <script>explorer.outline.writeEnabled = false;</script> 8caee17864 2010-11-24 kinaba: 8caee17864 2010-11-24 kinaba: <dd><p> 8caee17864 2010-11-24 kinaba: 組み込み関数・変数の一覧。 8caee17864 2010-11-24 kinaba: </p> 8caee17864 2010-11-24 kinaba: 8caee17864 2010-11-24 kinaba: <script>explorer.outline.incSymbolLevel();</script> 8caee17864 2010-11-24 kinaba: <dl> 8caee17864 2010-11-24 kinaba: <script>explorer.outline.writeEnabled = true;</script> 8caee17864 2010-11-24 kinaba: <dt><span class="decl"> 8caee17864 2010-11-24 kinaba: <span class="currsymbol">テーブル操作</span> 8caee17864 2010-11-24 kinaba: <script>explorer.outline.addDecl('テーブル操作');</script> 8caee17864 2010-11-24 kinaba: 8caee17864 2010-11-24 kinaba: </span></dt> 8caee17864 2010-11-24 kinaba: <script>explorer.outline.writeEnabled = false;</script> 8caee17864 2010-11-24 kinaba: 8caee17864 2010-11-24 kinaba: <dd> <table> <tr><th>{}</th> <td>()</td> <td>空のテーブルを作る</td></tr> 8caee17864 2010-11-24 kinaba: <tr><th>.</th> <td>(t, s)</td> <td>テーブル t の名前 s のフィールドの値を取得。なければ <tt>undefined</tt></td></tr> 8caee17864 2010-11-24 kinaba: <tr><th>.?</th> <td>(t, s)</td> <td>テーブル t に名前 s のフィールドがあれば 1、なければ 0</td></tr> 8caee17864 2010-11-24 kinaba: <tr><th>.=</th> <td>(t, s, v)</td> <td>テーブル t を親に持ち、名前 s のフィールドに v が入ったテーブルを作る</td></tr> 8caee17864 2010-11-24 kinaba: </table> 8caee17864 2010-11-24 kinaba: </dd> 8caee17864 2010-11-24 kinaba: <br /> 8caee17864 2010-11-24 kinaba: 8caee17864 2010-11-24 kinaba: 8caee17864 2010-11-24 kinaba: <script>explorer.outline.writeEnabled = true;</script> 8caee17864 2010-11-24 kinaba: <dt><span class="decl"> 8caee17864 2010-11-24 kinaba: <span class="currsymbol">制御フロー</span> 8caee17864 2010-11-24 kinaba: <script>explorer.outline.addDecl('制御フロー');</script> 8caee17864 2010-11-24 kinaba: 8caee17864 2010-11-24 kinaba: </span></dt> 8caee17864 2010-11-24 kinaba: <script>explorer.outline.writeEnabled = false;</script> 8caee17864 2010-11-24 kinaba: 8caee17864 2010-11-24 kinaba: <dd> <table> <tr><th>if</th> <td>(n, ft, fe)</td> <td>n が非 0 なら <tt>ft()</t>、0 なら <tt>fe()</tt> を実行</td></tr> 8caee17864 2010-11-24 kinaba: </table> 8caee17864 2010-11-24 kinaba: </dd> 8caee17864 2010-11-24 kinaba: <br /> 8caee17864 2010-11-24 kinaba: 8caee17864 2010-11-24 kinaba: 8caee17864 2010-11-24 kinaba: <script>explorer.outline.writeEnabled = true;</script> 8caee17864 2010-11-24 kinaba: <dt><span class="decl"> 8caee17864 2010-11-24 kinaba: <span class="currsymbol">演算</span> 8caee17864 2010-11-24 kinaba: <script>explorer.outline.addDecl('演算');</script> 8caee17864 2010-11-24 kinaba: 8caee17864 2010-11-24 kinaba: </span></dt> 8caee17864 2010-11-24 kinaba: <script>explorer.outline.writeEnabled = false;</script> 8caee17864 2010-11-24 kinaba: 8caee17864 2010-11-24 kinaba: <dd> <table> <tr><th>+</th> <td>(n, m)</td> <td>整数 n と整数 m を足して返す</td></tr> 8caee17864 2010-11-24 kinaba: <tr><th>-</th> <td>(n, m)</td> <td>整数の引き算</td></tr> 8caee17864 2010-11-24 kinaba: <tr><th>*</th> <td>(n, m)</td> <td>整数の掛け算</td></tr> 8caee17864 2010-11-24 kinaba: <tr><th>/</th> <td>(n, m)</td> <td>整数の割り算</td></tr> 8caee17864 2010-11-24 kinaba: <tr><th>%</th> <td>(n, m)</td> <td>整数の剰余</td></tr> 8caee17864 2010-11-24 kinaba: <tr><th>&&</th> <td>(n, m)</td> <td>整数 n と m が両方非 0 なら 1、それ以外では 0</td></tr> 8caee17864 2010-11-24 kinaba: <tr><th>||</th> <td>(n, m)</td> <td>整数 n と m がどちらか非 0 なら 1、それ以外では 0</td></tr> 8caee17864 2010-11-24 kinaba: <tr><th>~</th> <td>(a, b)</td> <td>a と b を文字列化して結合</td></tr> 8caee17864 2010-11-24 kinaba: <tr><th><</th> <td>(a, b)</td> <td>a と b を比較</td></tr> 8caee17864 2010-11-24 kinaba: <tr><th><=</th> <td>(a, b)</td> <td>a と b を比較</td></tr> 8caee17864 2010-11-24 kinaba: <tr><th>></th> <td>(a, b)</td> <td>a と b を比較</td></tr> 8caee17864 2010-11-24 kinaba: <tr><th>>=</th> <td>(a, b)</td> <td>a と b を比較</td></tr> 8caee17864 2010-11-24 kinaba: <tr><th>==</th> <td>(a, b)</td> <td>a と b を比較</td></tr> 8caee17864 2010-11-24 kinaba: <tr><th>!=</th> <td>(a, b)</td> <td>a と b を比較</td></tr> 8caee17864 2010-11-24 kinaba: </table> 8caee17864 2010-11-24 kinaba: <p> 8caee17864 2010-11-24 kinaba: 注意点として、作者の趣味の問題で、<tt>&&</tt> と <tt>||</tt> は short-circuit 評価をしません。 8caee17864 2010-11-24 kinaba: 整数演算の種類が少ないのは、D 言語の std.bigint がビット演算などをサポートしてないためです。 8caee17864 2010-11-24 kinaba: 文字列が結合しかできないのは、単に手抜きです。 8caee17864 2010-11-24 kinaba: </p> 8caee17864 2010-11-24 kinaba: </dd> 8caee17864 2010-11-24 kinaba: 8caee17864 2010-11-24 kinaba: 8caee17864 2010-11-24 kinaba: <script>explorer.outline.writeEnabled = true;</script> 8caee17864 2010-11-24 kinaba: <dt><span class="decl"> 8caee17864 2010-11-24 kinaba: <span class="currsymbol">外部とのやりとり</span> 8caee17864 2010-11-24 kinaba: <script>explorer.outline.addDecl('外部とのやりとり');</script> 8caee17864 2010-11-24 kinaba: 8caee17864 2010-11-24 kinaba: </span></dt> 8caee17864 2010-11-24 kinaba: <script>explorer.outline.writeEnabled = false;</script> 8caee17864 2010-11-24 kinaba: 474c4facf0 2010-11-25 kinaba: <dd> <table> <tr><th>print</th> <td>(a)</td> <td>a を文字列化標準出力に改行付きで表示して、a を返す</td></tr> 8caee17864 2010-11-24 kinaba: <tr><th>argv</th> <td></td> <td>スクリプトに渡された引数文字列のconsリスト</td></tr> 474c4facf0 2010-11-25 kinaba: <tr><th>gensym</th> <td>()</td> <td>エセgensym。変数名として他とかぶらなそうな文字列を返します</td></tr> 474c4facf0 2010-11-25 kinaba: <tr><th>rand</th> <td>(n)</td> <td>0 以上 n 未満の自然数を31bit以内でランダムに生成します</td></tr> 8caee17864 2010-11-24 kinaba: </table> 8caee17864 2010-11-24 kinaba: </dd> 8caee17864 2010-11-24 kinaba: <br /> 8caee17864 2010-11-24 kinaba: 8caee17864 2010-11-24 kinaba: 8caee17864 2010-11-24 kinaba: <script>explorer.outline.writeEnabled = true;</script> 8caee17864 2010-11-24 kinaba: <dt><span class="decl"> 8caee17864 2010-11-24 kinaba: <span class="currsymbol">データ型判定</span> 8caee17864 2010-11-24 kinaba: <script>explorer.outline.addDecl('データ型判定');</script> 8caee17864 2010-11-24 kinaba: 8caee17864 2010-11-24 kinaba: </span></dt> 8caee17864 2010-11-24 kinaba: <script>explorer.outline.writeEnabled = false;</script> 8caee17864 2010-11-24 kinaba: 8caee17864 2010-11-24 kinaba: <dd> <table> <tr><th>_isint</th> <td>(a)</td> <td>a が整数なら 1、でなければ 0</td></tr> 8caee17864 2010-11-24 kinaba: <tr><th>_isstr</th> <td>(a)</td> <td>a が文字列なら 1、でなければ 0</td></tr> 8caee17864 2010-11-24 kinaba: <tr><th>_isfun</th> <td>(a)</td> <td>a が関数なら 1、でなければ 0</td></tr> 8caee17864 2010-11-24 kinaba: <tr><th>_istable</th> <td>(a)</td> <td>a がテーブルなら 1、でなければ 0</td></tr> 8caee17864 2010-11-24 kinaba: <tr><th>_isundefined</th> <td>(a)</td> <td>a が未定義値なら 1、でなければ 0</td></tr> 8caee17864 2010-11-24 kinaba: </table> 8caee17864 2010-11-24 kinaba: </dd> 8caee17864 2010-11-24 kinaba: </dl> 8caee17864 2010-11-24 kinaba: <script>explorer.outline.decSymbolLevel();</script> 8caee17864 2010-11-24 kinaba: 8caee17864 2010-11-24 kinaba: 8caee17864 2010-11-24 kinaba: </dd> 8caee17864 2010-11-24 kinaba: 8caee17864 2010-11-24 kinaba: </dl> 8caee17864 2010-11-24 kinaba: <script>explorer.outline.decSymbolLevel();</script> 8caee17864 2010-11-24 kinaba: 8caee17864 2010-11-24 kinaba: 8caee17864 2010-11-24 kinaba: </td></tr> 8caee17864 2010-11-24 kinaba: <tr><td id="docfooter"> 8caee17864 2010-11-24 kinaba: Page was generated with 8caee17864 2010-11-24 kinaba: <img src="candydoc/img/candydoc.gif" style="vertical-align:middle; position:relative; top:-1px"> 207cea338a 2010-11-26 kinaba: on Fri Nov 26 10:02:52 2010 8caee17864 2010-11-24 kinaba: 8caee17864 2010-11-24 kinaba: </td></tr> 8caee17864 2010-11-24 kinaba: </table> 8caee17864 2010-11-24 kinaba: </div> 8caee17864 2010-11-24 kinaba: <script> 8caee17864 2010-11-24 kinaba: explorer.packageExplorer.addModule("index"); 8caee17864 2010-11-24 kinaba: explorer.packageExplorer.addModule("main"); 8caee17864 2010-11-24 kinaba: explorer.packageExplorer.addModule("tricks.tricks"); 8caee17864 2010-11-24 kinaba: explorer.packageExplorer.addModule("tricks.test"); 8caee17864 2010-11-24 kinaba: explorer.packageExplorer.addModule("polemy._common"); 8caee17864 2010-11-24 kinaba: explorer.packageExplorer.addModule("polemy.failure"); 8caee17864 2010-11-24 kinaba: explorer.packageExplorer.addModule("polemy.layer"); 8caee17864 2010-11-24 kinaba: explorer.packageExplorer.addModule("polemy.fresh"); 8caee17864 2010-11-24 kinaba: explorer.packageExplorer.addModule("polemy.lex"); 8caee17864 2010-11-24 kinaba: explorer.packageExplorer.addModule("polemy.parse"); 8caee17864 2010-11-24 kinaba: explorer.packageExplorer.addModule("polemy.ast"); 8caee17864 2010-11-24 kinaba: explorer.packageExplorer.addModule("polemy.value"); 8caee17864 2010-11-24 kinaba: explorer.packageExplorer.addModule("polemy.valueconv"); 8caee17864 2010-11-24 kinaba: explorer.packageExplorer.addModule("polemy.eval"); 8caee17864 2010-11-24 kinaba: explorer.packageExplorer.addModule("polemy.runtime"); 8caee17864 2010-11-24 kinaba: explorer.packageExplorer.addModule("polemy.repl");</script> 8caee17864 2010-11-24 kinaba: </body></html> 8caee17864 2010-11-24 kinaba: 8caee17864 2010-11-24 kinaba: