Diff
Not logged in

Differences From Artifact [f78a001ef162c560]:

To Artifact [07bae30af3901ecf]:


8 8 <p> 9 9 あとついでに、左のサイドバーの "Package" タブをクリックすると実装のソースのドキュメントが読めます。 10 10 </p> 11 11 12 12 $(DDOC_MEMBERS 13 13 14 14 $(SECTION Syntax, $(SECBODY 15 - 16 15 <p> 17 16 文法について。 18 17 字句解析がわりと適当なので、 19 18 変数宣言の変数名のところに、数字を変数名として使えて参照できない変数が作れたり、 20 19 予約語は予約語として解釈され得ないところでは普通に変数名として使えちゃったりして、 21 20 偶にとんでもない見かけのソースが構文解析通りますが、気にしないで適当に使って下さい。 22 21 </p> ................................................................................ 89 88 <br/> 90 89 パターンマッチも全部 <tt>if</tt> と <tt>==</tt> と <tt>&amp;&amp;</tt> と 91 90 <tt>.</tt> と <tt>.?</tt> を使った関数呼び出し式に書き換えられていますが、 92 91 規則の詳細を説明するのが面倒なので適当に想像して下さい。 93 92 他の書き換えはこんな感じです。 94 93 </p> 95 94 <pre> 96 - if (E) then{E} ⇒ if( E, fun(){E}, fun(){} ) 97 - if (E) then{E} else{E} ⇒ if( E, fun(){E}, fun(){E} ) 98 - E BINOP E ⇒ BINOP(E, E) 99 - { ENTRIES } ⇒ {}{ ENTRIES } 100 - {} ⇒ {}() 101 - E {ID:E, ...} ⇒ .=(E, ID, E) { ... } 95 + if (E) {E} ⇒ if( E, fun(){E}, fun(){} ) 96 + if (E) {E} else {E} ⇒ if( E, fun(){E}, fun(){E} ) 97 + E BINOP E ⇒ BINOP(E, E) 98 + { ENTRIES } ⇒ {}{ ENTRIES } 99 + {} ⇒ {}() 100 + E {ID:E, ...} ⇒ .=(E, ID, E) { ... } 102 101 </pre> 103 102 <p> 104 103 変数宣言に色々ありますが、<tt>let</tt> と <tt>var</tt> と <tt>def</tt> は同じ扱いで、 105 104 <tt>in</tt> と <tt>;</tt> は同じ扱いです。つまり 106 105 </p> 107 106 <pre> 108 107 let x = E in E ................................................................................ 135 134 <p> 136 135 中身が空の関数に何を返させるかは適当です。今はとりあえず適当に文字列返してます。 137 136 </p> 138 137 )) 139 138 140 139 $(SECTION 変数のスコープ規則, $(SECBODY 141 140 <p> 142 -NOTE: Theres no "let rec" syntax, but still recursive definition works 143 - def f(x) { if(x==0){1}else{x*f(x-1)} } in f(10) #=> 3628800 144 - yet still the code below also works 145 - def x=21 in def x=x+x in x #=> 42. 146 - The internal scoping mechanism is a little tricky (this is for coping with 147 - the "layer" feature explained below), but I hope that it works as everyone 148 - expects in most cases, as long as you don't use the same-name-variables heavily :). 141 +基本的には、let によって常識的な感じに変数のスコープがネストします。 142 +</p> 143 +<pre> 144 + let x=21 in let x=x+x in x $(D_COMMENT # 42) 145 +</pre> 146 +<p> 147 +一方で、"let rec" のような特別な構文はありませんが、 148 +</p> 149 +<pre> 150 + let f = fun(x) { if(x==0){1}else{x*f(x-1)} } in f(10) $(D_COMMENT # 3628800) 151 +</pre> 152 +<p> 153 +再帰的な関数定義なども、おそらく意図されたとおりに動きます。 154 +内部の詳細は、諸般の事情により、 155 +マジカルで破壊的なスコープ規則になっているのですが、 156 +同名の変数を激しく重ねて使ったりしなければ、 157 +だいたい自然な動きをすると思います、たぶん、はい。 158 +</p> 159 +<p> 160 +ひとつだけ不可思議な動きをするのは、以下のケースです。 161 +</p> 162 +<pre> 163 + let x = 1 in 164 + let f = fun() {x} in 165 + let x = 2 in 166 + f() $(D_COMMENT # 2!!) 167 +</pre> 168 +<p> 169 +let-in を縦にチェインしたときだけ、同名変数を破壊的に上書きします 170 +(再帰関数の定義が"うまく"いっているのはこの上書きのためです)。 171 +なんでこんなことになっているかというと、 172 +後で説明する「レイヤ」を使ったときに 173 +<tt>let foo = ... in @lay foo = ... in ...</tt> 174 +で他レイヤに重ね書きするためであります。 149 175 </p> 150 176 )) 151 - 177 +) 152 178 )) 153 179 154 180 155 181 156 182 157 183 $(SECTION Basic Features, $(SECBODY 158 184 <p> ................................................................................ 183 209 関数はいわゆる「クロージャ」です。静的スコープで外側の環境にアクセスできます。 184 210 テーブルはいわゆるプロトタイプチェーンを持っていて、 185 211 自分にないフィールドの場合は親に問い合わせが行く感じになっていますが、 186 212 フィールドの書き換えがないので、これは特に意味ないかもしれない…。 187 213 </p> 188 214 )) 189 215 $(SECTION パターンマッチ, $(SECBODY 190 -pattern matching is also available. Here is an example. 191 - 192 - def adjSum(lst) 193 - { 194 - case( lst ) 195 - when( {car:x, cdr:{car: y, cdr:z}} ) { {car: x+y, cdr: adjSum(z)} } 196 - when( {car:x, cdr:{}} ) { {car: x, cdr: {}} } 197 - when( {} ) { {} } 198 - }; 199 - 200 -It is expanded to a sequence of if-then-elses prefering the first-match. 201 -Note that {a: _} pattern matches all the tables that have the .a field. 202 -It also matches to {a: 123, b: 456} having extra .b field. So, changing the 203 -order of "when"s in the above code changes the behavior. 216 +<p> 217 +適当に実装されたパターンマッチがあります。 218 +リストの 2n 番目と 2n+1 番目を足して長さを半分にする関数: 219 +</p> 220 +<pre> 221 + def adjSum(lst) 222 + { 223 + case( lst ) 224 + when( {car:x, cdr:{car: y, cdr:z}} ) { {car: x+y, cdr: adjSum(z)} } 225 + when( {car:x, cdr:{}} ) { lst } 226 + when( {} ) { {} } 227 + } 228 +</pre> 229 +<p> 230 +動かすときには、処理系がそれっぽい if-then-else に展開しています。 231 +<tt>when</tt> を上から試していって、最初にマッチしたところを実行します。 232 +</p> 233 +<pre> 234 + PAT ::= "_" $(D_COMMENT # ワイルドカード) 235 + | ID $(D_COMMENT # 変数パターン) 236 + | "{" ID ":" PAT "," ... "," ID : PAT "}" $(D_COMMENT # テーブルパターン) 237 + | E $(D_COMMENT # 値パターン) 238 +</pre> 239 +<p> 240 +変数パターンは常にマッチして、値をその変数に束縛します。 241 +ワイルドカードも常にマッチしますが、変数束縛しません。 242 +値パターンは、任意の式が書けます。その式を評価した結果と <tt>==</tt> ならマッチします。 243 +外で束縛された変数を値パターンとして配置、は直接はできないので 244 +</p> 245 +<pre> 246 + var x = 123; 247 + case( foo ) 248 + when( {val: x+0} ) { ... } $(D_COMMENT # これは任意の {val:123} と同じ) 249 + when( {val: x} ) { ... } $(D_COMMENT # これは任意の foo.?val なら常にマッチ) 250 +</pre> 251 +<p> 252 +適当にちょっと複雑な式にしてやるとよいかも(裏技)。 253 +</p> 254 +<p> 255 +テーブルパターンは、書かれたキーが全てあればマッチします。 256 +<tt>{a: _}</tt> は、<tt>.a</tt> を持ってさえいればマッチするので、 257 +<tt>{a: 123, b: 456}</tt> なんかにもマッチします。 258 +なので、リストに対するパターンを書くときには、car/cdr の場合を先に書かないと 259 +<tt>when({})</tt> を上に書くと全部マッチしちゃいます。注意。 260 +</p> 204 261 )) 205 262 ) 206 263 )) 207 264 208 265 209 266 210 267 ................................................................................ 355 412 is@value:app, arg@value:{... 356 413 /fst@value:3 357 414 /} 358 415 359 416 its corresponding arguments are evaluated in the layer and passed to it. 360 417 If you specify multiple layers, the argument expression is run multiple times. 361 418 If you do not specify any layer for a parameter, it works in the neutral layer. 419 +</pre> 420 +)) 362 421 363 422 423 +$(SECTION Macro Layers, $(SECBODY 424 +<p> 425 +Polemy 言語組み込みのレイヤは <code>@value</code> と <code>@macro</code> の二つです。 426 +(内部的にはもういくつかありますが、ユーザから直接は使えません。) 427 +<code>@value</code> は、「普通に」普通のセマンティクスでプログラムを実行するレイヤでした。 428 +<code>@macro</code> は、実は、<code>@value</code> よりも前に実行されるレイヤで、 429 +「プログラムを実行するとその構文木を返す」というセマンティクスで動きます。 430 +</p> 431 +<pre> 432 + (ここに例) 433 +</pre> 434 +<p> 435 +動きとしてはこうです。 436 +</p> 437 +<ol> 438 +<li>関数呼び出し時(とトップレベル環境の実行開始時)に、 439 + まず、<code>@macro</code> レイヤでコードを実行。</li> 440 +<li>返ってきた構文木を、<code>@value</code> レイヤ、 441 + またはその関数を呼び出したときのレイヤで実行。</li> 442 +</ol> 443 +<p> 444 +<code>@macro</code> レイヤも所詮ただのレイヤですので、 445 +上で説明した方法で <code>@macro</code> レイヤに関数などを登録しておくことで、 446 +構文木の生成をいじることが可能です。まさにマクロ。 447 +</p> 364 448 365 -[@macro layer] 366 - 449 +$(DDOC_MEMBERS 450 +$(SECTION 使い方, $(SECBODY 451 +<pre> 367 452 When function is invoked, it first run in the @macro layer, and after that, 368 453 it run in the neutral layer. Here is an example. 369 454 370 455 >> @macro twice(x) { x; x } 371 456 >> def f() { twice(print("Hello")); 999 } 372 457 (function:173b6a0:1789720) 373 458 >> f() ................................................................................ 380 465 in the @macro layer. Basically what it does is to just construct its syntax tree. 381 466 But, since we have defined the "twice" function in the @macro layer, it is 382 467 execute as a function. Resulting syntax tree is 383 468 "print("Hello"); print("Hello"); 999" 384 469 and this is executed on the neutral (in this example, @value) layer. 385 470 This is the reason why you see two "Hello"s. 386 471 472 + [[quote and unquote]] 387 473 474 + Here is more involved example of code genration. 475 + From "x", it generates "x*x*x*x*x*x*x*x*x*x". 476 + 477 + @macro pow10(x) { 478 + @value( 479 + def pow(x, n) { 480 + if( n == 1 ) { x } 481 + else { 482 + @macro( @value(x) * @value(pow(x,n-1)) ) 483 + } 484 + } 485 + in 486 + pow(@macro(x),10) 487 + ) 488 + }; 489 + 490 + Here, x is a syntax tree but n is an actual integer. If you read carefully, 491 + you should get what is going on. Basically, @macro can be considered like 492 + quasiquoting and @value to be an escape from it. 493 +</pre> 494 +)) 495 +$(SECTION 微妙な挙動, $(SECBODY 496 +<pre> 497 + (rawmacro) レイヤの話 388 498 389 499 [[limitations]] 390 500 391 501 This @macro layer is a very primitive one, and not a perfect macro language. 392 502 Two major limitations are seen in the following "it" example. 393 503 394 504 >> @macro LetItBe(x, y) { let it = x in y }; ................................................................................ 407 517 So 408 518 409 519 >> LetItBe( 1+2+3, it*it ) 410 520 ...\value.d(173): [<REPL>:24:1] variable LetItBe is not set in layer @value 411 521 412 522 you cannot directly use the macro in the same scope as the definition. 413 523 You need to wrap it up in a function (like the foo() in the above example). 414 - 415 - 416 - 417 - [[quote and unquote]] 418 - 419 - Here is more involved example of code genration. 420 - From "x", it generates "x*x*x*x*x*x*x*x*x*x". 421 - 422 - @macro pow10(x) { 423 - @value( 424 - def pow(x, n) { 425 - if( n == 1 ) { x } 426 - else { 427 - @macro( @value(x) * @value(pow(x,n-1)) ) 428 - } 429 - } 430 - in 431 - pow(@macro(x),10) 432 - ) 433 - }; 434 - 435 - Here, x is a syntax tree but n is an actual integer. If you read carefully, 436 - you should get what is going on. Basically, @macro can be considered like 437 - quasiquoting and @value to be an escape from it. 438 524 </pre> 525 +)) 526 +) 439 527 )) 440 528 441 529 442 530 $(SECTION Built-in Primitives, $(SECBODY 443 531 <p> 444 532 組み込み関数・変数の一覧。 445 533 </p>