1 Ddoc
2 $(DDOC_AUTHORS k.inaba)
3 $(DDOC_LICENSE NYSL 0.9982 (http://www.kmonos.net/nysl/))
4
5 <p>
6 このファイルは、言語仕様などの簡単な説明です。
7 </p>
8 <p>
9 あとついでに、左のサイドバーの "Package" タブをクリックすると実装のソースのドキュメントが読めます。
10 </p>
11
12 $(DDOC_MEMBERS
13
14 $(SECTION Syntax, $(SECBODY
15 <p>
16 文法について。
17 字句解析がわりと適当なので、
18 変数宣言の変数名のところに、数字を変数名として使えて参照できない変数が作れたり、
19 予約語は予約語として解釈され得ないところでは普通に変数名として使えちゃったりして、
20 偶にとんでもない見かけのソースが構文解析通りますが、気にしないで適当に使って下さい。
21 </p>
22
23 $(DDOC_MEMBERS
24
25 $(SECTION 文字コード, $(SECBODY
26 <p>
27 UTF-8 のみ対応です。
28 </p>
29 ))
30
31 $(SECTION コメント, $(SECBODY
32 <p>
33 行コメントは <tt>#</tt> から改行までです。
34 </p>
35 <p>
36 ブロックコメントはありません。
37 </p>
38 ))
39
40 $(SECTION BNF, $(SECBODY
41 <pre>
42 ID ::= 適当に識別子っぽい文字列
43 LAYER ::= "@" ID
44
45 E ::=
46 $(D_COMMENT # 変数宣言)
47 | ("var"|"let"|"def"|LAYER) ID "=" E (";"|"in") E
48 | ("var"|"let"|"def"|LAYER) ID "(" PARAMS ")" "{" E "}" (";"|"in") E
49 | ("var"|"let"|"def"|LAYER) ID "=" E
50 | ("var"|"let"|"def"|LAYER) ID "(" PARAMS ")" "{" E "}"
51
52 $(D_COMMENT # リテラル)
53 | INTEGER $(D_COMMENT # 非負整数)
54 | STRING $(D_COMMENT # "" でくくった文字列。\" と \\ は使える)
55 | "{" ENTRYS "}" $(D_COMMENT # テーブル)
56 | "fun" "(" PARAMS ")" "{" E "}" $(D_COMMENT # 無名関数)
57 | "λ" "(" PARAMS ")" "{" E "}" $(D_COMMENT # 無名関数)
58
59 $(D_COMMENT # 関数呼び出し)
60 | E "(" ARGS")"
61
62 where ARGS ::= E "," ... "," E
63 PARAMS ::= (ID|LAYER)+ "," ... "," (ID|LAYER)+
64 ENTRYS ::= ID ":" E "," ... "," ID ":" E
65
66 $(D_COMMENT # 演算子など)
67 | "(" E ")" $(D_COMMENT # ただの括弧)
68 | E BINOP E $(D_COMMENT # 二項演算子いろいろ)
69 | E "." ID $(D_COMMENT # テーブルのフィールドアクセス)
70 | E ".?" ID $(D_COMMENT # テーブルにフィールドがあるか否か)
71 | E "{" ENTRYS "}" $(D_COMMENT # テーブル拡張)
72 | "if" E ("then"|":"|"then" ":") E
73 | "if" E ("then"|":"|"then" ":") E "else" ":"? E
74
75 $(D_COMMENT # パターンマッチ)
76 | "case" E ("when" PATTERN ":" E )*
77
78 where PATTERN ::= 式がだいたいなんでも書ける気がする
79
80 $(D_COMMENT # レイヤ指定実行)
81 | LAYER "(" E ")"
82 </pre>
83 ))
84
85 $(SECTION 糖衣構文, $(SECBODY
86 <p>
87 演算子というものはありません。内部的には全て関数呼び出し構文に書き換えられています。<tt>if</tt> もです。
88 <br/>
89 パターンマッチも全部 <tt>if</tt> と <tt>==</tt> と <tt>&&</tt> と
90 <tt>.</tt> と <tt>.?</tt> を使った関数呼び出し式に書き換えられていますが、
91 規則の詳細を説明するのが面倒なので適当に想像して下さい。
92 他の書き換えはこんな感じです。
93 </p>
94 <pre>
95 if E then E ⇒ if( E, fun(){E}, fun(){} )
96 if E then 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) { ... }
101 </pre>
102 <p>
103 変数宣言に色々ありますが、<tt>let</tt> と <tt>var</tt> と <tt>def</tt> は同じ扱いで、
104 <tt>in</tt> と <tt>;</tt> は同じ扱いです。つまり
105 </p>
106 <pre>
107 let x = E in E
108 var x = E in E
109 def x = E in E
110 let x = E ; E
111 var x = E ; E
112 def x = E ; E
113 </pre>
114 <p>
115 以上のどれも同じ意味なので、なんとなく関数型っぽく書きたい気分の日は <tt>let in</tt> を、
116 手続き型っぽく書きたい気分の日は <tt>var ;</tt> を使うとよいと思います。
117 <tt>if then else</tt> も微妙にコロンがあったりなかったりバリエーションがありますが好みで使います。
118 </p>
119 <p>
120 関数を宣言するときは、<tt>fun</tt> や <tt>λ</tt> を省略できます。
121 以下の書き換えが行われます。
122 </p>
123 <pre>
124 def f( ARGS ) { E }; E ⇒ def f = fun(ARGS){E}; E
125 </pre>
126 <p>
127 他に、もっと手続き型っぽくための書き換え色々
128 </p>
129 <pre>
130 fun () { E; E; E } ⇒ fun () { let _ = E in let _ = E in E }
131 fun () { var x = 100 } ⇒ fun () { var x = 100; x }
132 fun () { var x = 100; } ⇒ fun () { var x = 100; x }
133 fun () { } ⇒ fun () { "(empty function body)" }
134 </pre>
135 <p>
136 中身が空の関数に何を返させるかは適当です。今はとりあえず適当に文字列返してます。
137 </p>
138 ))
139
140 $(SECTION 変数のスコープ規則, $(SECBODY
141 <p>
142 基本的には、let によって常識的な感じに変数のスコープがネストします。
143 </p>
144 <pre>
145 let x=21 in let x=x+x in x $(D_COMMENT # 42)
146 </pre>
147 <p>
148 一方で、"let rec" のような特別な構文はありませんが、
149 </p>
150 <pre>
151 let f = fun(x) { if x==0 then 1 else x*f(x-1) } in f(10) $(D_COMMENT # 3628800)
152 </pre>
153 <p>
154 再帰的な関数定義なども、おそらく意図されたとおりに動きます。
155 内部の詳細は、諸般の事情により、
156 マジカルで破壊的なスコープ規則になっているのですが、
157 同名の変数を激しく重ねて使ったりしなければ、
158 だいたい自然な動きをすると思います、たぶん、はい。
159 </p>
160 <p>
161 ひとつだけ不可思議な動きをするのは、以下のケースです。
162 </p>
163 <pre>
164 let x = 1 in
165 let f = fun() {x} in
166 let x = 2 in
167 f() $(D_COMMENT # 2!!)
168 </pre>
169 <p>
170 let-in を縦にチェインしたときだけ、同名変数を破壊的に上書きします
171 (再帰関数の定義が"うまく"いっているのはこの上書きのためです)。
172 なんでこんなことになっているかというと、
173 後で説明する「レイヤ」を使ったときに
174 <tt>let foo = ... in @lay foo = ... in ...</tt>
175 で他レイヤに重ね書きするためであります。
176 </p>
177 ))
178 )
179 ))
180
181
182
183
184 $(SECTION Basic Features, $(SECBODY
185 <p>
186 特に特徴的でもない部分を簡単にまとめ。
187 </p>
188 <ul>
189 <li>静的型システムはありません。</li>
190 <li>"ほぼ" 純粋関数型言語です。変数やテーブルのフィールドの破壊的な書き換えはできません。<br/>
191 ただし、組み込み関数(<tt>print</tt>)と、変数のスコープ規則のマジカルな片隅に副作用があります。</li>
192 </ul>
193 <p>
194 静的型システムがないのは意図的ですが、破壊的代入がないのは、単に実装がめんどかっただけなので、
195 今後何か増えるかもしれません。増えないかもしれません。
196 </p>
197 $(DDOC_MEMBERS
198 $(SECTION データ型, $(SECBODY
199 <p>
200 以下のデータ型があります。
201 </p>
202 <ul>
203 <li>整数: <tt>0</tt>, <tt>123</tt>, <tt>456666666666666666666666666666666666666789</tt>, ...</li>
204 <li>文字列: <tt>"hello, world!"</tt>, ...</li>
205 <li>関数: <tt>fun(x){x+1}</tt></li>
206 <li>テーブル: <tt>{car: 1, cdr: {car: 2, cdr: {}}}</tt></li>
207 <li>未定義値: (undefined。特殊なケースで作られます)</li>
208 </ul>
209 <p>
210 関数はいわゆる「クロージャ」です。静的スコープで外側の環境にアクセスできます。
211 テーブルはいわゆるプロトタイプチェーンを持っていて、
212 自分にないフィールドの場合は親に問い合わせが行く感じになっていますが、
213 フィールドの書き換えがないので、これは特に意味ないかもしれない…。
214 </p>
215 <p>
216 また、リストを扱うために、いわゆる「cons リスト」を使います。
217 空リストを <tt>{}</tt>、1個以上要素があるものを <tt>{car: 先頭要素, cdr: 二番目以降のリスト}</tt>
218 という形で。この形でリストを扱わなければならないという決まりはありませんが、
219 この形は特別扱いされて <tt>print</tt> で綺麗に出力されたりします。
220 </p>
221 ))
222 $(SECTION パターンマッチ, $(SECBODY
223 <p>
224 適当に実装されたパターンマッチがあります。
225 リストの 2n 番目と 2n+1 番目を足して長さを半分にする関数:
226 </p>
227 <pre>
228 def adjSum(lst)
229 {
230 case lst
231 when {car:x, cdr:{car: y, cdr:z}}: {car: x+y, cdr: adjSum(z)}
232 when {car:x, cdr:{}}: lst
233 when {}: {}
234 }
235 </pre>
236 <p>
237 動かすときには、処理系がそれっぽい if-then-else に展開しています。
238 <tt>when</tt> を上から試していって、最初にマッチしたところを実行します。
239 </p>
240 <pre>
241 PAT ::= "_" $(D_COMMENT # ワイルドカード)
242 | ID $(D_COMMENT # 変数パターン)
243 | "{" ID ":" PAT "," ... "," ID : PAT "}" $(D_COMMENT # テーブルパターン)
244 | E $(D_COMMENT # 値パターン)
245 </pre>
246 <p>
247 変数パターンは常にマッチして、値をその変数に束縛します。
248 ワイルドカードも常にマッチしますが、変数束縛しません。
249 値パターンは、任意の式が書けます。その式を評価した結果と <tt>==</tt> ならマッチします。
250 外で束縛された変数を値パターンとして配置、は直接はできないので
251 </p>
252 <pre>
253 var x = 123;
254 case foo
255 when {val: x+0}: ... $(D_COMMENT # これは {val:123} と同じ)
256 when {val: x}: ... $(D_COMMENT # これは任意の foo.?val なら常にマッチ)
257 </pre>
258 <p>
259 適当にちょっと複雑な式にしてやるとよいかも(裏技)。
260 </p>
261 <p>
262 テーブルパターンは、書かれたキーが全てあればマッチします。
263 <tt>{a: _}</tt> は、<tt>.a</tt> を持ってさえいればマッチするので、
264 <tt>{a: 123, b: 456}</tt> なんかにもマッチします。
265 なので、リストに対するパターンを書くときには、car/cdr の場合を先に書かないと
266 <tt>when {}</tt> を上に書くと全部マッチしちゃいます。注意。
267 </p>
268 ))
269 )
270 ))
271
272
273
274
275
276 $(SECTION Layers, $(SECBODY
277 <pre>
278 [Layers :: Overview]
279
280 Polemy's runtime environment has many "layer"s.
281 Usual execution run in the @value layer.
282
283 >> 1 + 2
284 3
285 >> @value( 1 + 2 )
286 3
287
288 Here you can see that @LayerName( Expression ) executes the inner Expression in
289 the @LayerName layer. Other than @value, one other predefined layer exists: @macro.
290
291 >> @macro( 1+2 )
292 {pos@value:{lineno@value:3, column@value:9, filename@value:<REPL>},
293 is@value:app,
294 args@value:{car@value:{pos@value:{lineno@value:3, column@value:9, filename@value:<REPL>},
295 is@value:int,
296 data@value:1},
297 cdr@value:{
298 car@value:{pos@value:{lineno@value:3, column@value:11, filename@value:<REPL>},
299 is@value:int,
300 data@value:2},
301 cdr@value:{}}},
302 fun@value:{pos@value:{lineno@value:3, column@value:10, filename@value:<REPL>},
303 is@value:var,
304 name@value:+}}
305
306 (Sorry, this pretty printing is not available on the actual interpreter...)
307 This evaluates the expression 1+2 in the @macro layer. In this layer, the meaning of
308 the program is its abstract syntax tree.
309
310 You can interleave layers.
311 The root node of the abstract syntax tree is function "app"lication.
312
313 >> @value(@macro( 1+2 ).is)
314 app
315
316
317
318 [Layers :: Defining a new layer]
319
320 To define a new layer, you should first tell how to "lift" existing values two the new layer.
321 Let us define the "@type" layer, where the meaning of programs is their static type.
322
323 >> @@type = fun(x) {
324 >> if( _isint(x) ) { "int" } else {
325 >> if( _isfun(x) ) { x } else { "unknown" } }
326 >> }
327 (Note: polemy REPL may warn some exception here but please ignore)
328
329 For simplicity, I here deal only with integers.
330 _isint is a primitive function of Polemy that checks the dynamic type of a value.
331 For function, leaving it untouched works well for almost all layers.
332
333 >> @type( 1 )
334 int
335 >> @type( 2 )
336 int
337 >> @type( "foo" )
338 unknown
339
340 Fine! Let's try to type 1+2.
341
342 >> @type( 1 + 2 )
343 ...\value.d(119): [<REPL>:6:8] only @value layer can call native function
344
345 Note that the behavior of this program is
346 - run 1+2 in the @type layer
347 and NOT
348 - run 1+2 in @value and obtain 3 and run 3 in the @type.
349 The problem is, the variable "+" is defined only in the @value layer.
350 To carry out computation in the @type layer. We need to define it also
351 in the @type layer.
352
353 To define some variable in a specific layer, use @LayerName in place of
354 (let|var|def)s.
355
356 >> let x = 2
357 >> @value x = 2
358 >> @type x = "int"
359 >> @hoge x = "fuga"
360
361 For "+", do it like this.
362
363 >> @type "+" = fun(x,y) {@value(
364 >> if( @type(x)=="int" && @type(y)=="int" ) { "int" } else { "typeerror" }
365 >> )}
366 polemy.value.native!(IntValue,IntValue,IntValue).native.__anonclass24
367
368 It is just computing the return type from the input type.
369 Not here that the intended "meaning" of if-then-else is the runtime-branching,
370 and the meaning of "==" is the value-comparison. These are the @value layer
371 behavior. So we have defined the function body inside @value layer.
372 But when we refer the variables x and y, we need its @type layer meaning.
373 Hence we use @type() there.
374
375 Now we get it.
376
377 >> @type( 1 + 2 )
378 int
379
380 Well, but do we have to define the @type layer meaning for every variables???
381 No. After you defined @type "+", you'll automatically get the following:
382
383 >> def double(x) { x + x }
384 (function:17e4740:1789720)
385
386 >> @type( double(123) )
387 int
388
389 Every user-defined functions are automatically "lift"ed to the appropriate layer.
390 Only primitive functions like "+" requires @yourNewLayer annotation.
391
392
393
394 [Layers :: neutral-layer]
395
396 let|var|def is to define a variable in the "current" layer.
397 Not necessary to the @value layer.
398
399 >> @value( let x = 1 in @value(x) )
400 1
401
402 >> @macro( let x = 1 in @value(x) )
403 polemy.failure.RuntimeException: [<REPL>:14:29] variable x not found
404
405 >> @macro( let x = 1 in @macro(x) )
406 {pos@value:{lineno@value:15, ...
407
408
409
410 [Layers :: Layered-Parameters]
411
412 >> def foo(x @macro @value) { {fst: x, snd: @macro(x)} }
413 (function:1730360:1789720)
414
415 If you annotate function parameters by @LayerNames, when you invoke the function...
416
417 >> foo(1+2)
418 {snd@value: {pos@value:{lineno@value:17, column@value:5, filename@value:<REPL>},
419 is@value:app, arg@value:{...
420 /fst@value:3
421 /}
422
423 its corresponding arguments are evaluated in the layer and passed to it.
424 If you specify multiple layers, the argument expression is run multiple times.
425 If you do not specify any layer for a parameter, it works in the neutral layer.
426 </pre>
427 ))
428
429
430 $(SECTION Macro Layers, $(SECBODY
431 <p>
432 Polemy 言語組み込みのレイヤは <code>@value</code> と <code>@macro</code> の二つです。
433 (内部的にはもういくつかありますが、ユーザから直接は使えません。)
434 <code>@value</code> は、「普通に」普通のセマンティクスでプログラムを実行するレイヤでした。
435 <code>@macro</code> は、実は、<code>@value</code> よりも前に実行されるレイヤで、
436 「プログラムを実行するとその構文木を返す」というセマンティクスで動きます。
437 </p>
438 <pre>
439 (ここに例)
440 </pre>
441 <p>
442 動きとしてはこうです。
443 </p>
444 <ol>
445 <li>関数呼び出し時(とトップレベル環境の実行開始時)に、
446 まず、<code>@macro</code> レイヤでコードを実行。</li>
447 <li>返ってきた構文木を、<code>@value</code> レイヤ、
448 またはその関数を呼び出したときのレイヤで実行。</li>
449 </ol>
450 <p>
451 <code>@macro</code> レイヤも所詮ただのレイヤですので、
452 上で説明した方法で <code>@macro</code> レイヤに関数などを登録しておくことで、
453 構文木の生成をいじることが可能です。まさにマクロ。
454 </p>
455
456 $(DDOC_MEMBERS
457 $(SECTION 使い方, $(SECBODY
458 <pre>
459 When function is invoked, it first run in the @macro layer, and after that,
460 it run in the neutral layer. Here is an example.
461
462 >> @macro twice(x) { x; x }
463 >> def f() { twice(print("Hello")); 999 }
464 (function:173b6a0:1789720)
465 >> f()
466 Hello
467 Hello
468 999
469
470 When the interpreter evaluates f(), it first executes
471 "twice(print("Hello")); 999"
472 in the @macro layer. Basically what it does is to just construct its syntax tree.
473 But, since we have defined the "twice" function in the @macro layer, it is
474 execute as a function. Resulting syntax tree is
475 "print("Hello"); print("Hello"); 999"
476 and this is executed on the neutral (in this example, @value) layer.
477 This is the reason why you see two "Hello"s.
478
479 [[quote and unquote]]
480
481 Here is more involved example of code genration.
482 From "x", it generates "x*x*x*x*x*x*x*x*x*x".
483
484 @macro pow10(x) {
485 @value(
486 def pow(x, n) {
487 if( n == 1 ) { x }
488 else {
489 @macro( @value(x) * @value(pow(x,n-1)) )
490 }
491 }
492 in
493 pow(@macro(x),10)
494 )
495 };
496
497 Here, x is a syntax tree but n is an actual integer. If you read carefully,
498 you should get what is going on. Basically, @macro can be considered like
499 quasiquoting and @value to be an escape from it.
500 </pre>
501 <p>
502 構文木がどのようなテーブルで渡されてくるかについては、ソースドキュメントの
503 <a href="http://www.kmonos.net/repos/polemy/doc/tip/doc/ast.html">polemy.ast</a>
504 のページをご覧下さい。例えば変数名を表す <code>Var</code> クラスには、
505 継承の分も合わせて
506 <tt><a href="http://www.kmonos.net/repos/polemy/doc/tip/doc/failure.html">LexPosition</a> pos;</tt>
507 と <tt>string name;</tt> の2つのメンバがあるので
508 </p>
509 <pre>
510 { is: "Var",
511 pos: {filename:"foo.pmy", lineno:123, column:45},
512 name: "x" }
513 </pre>
514 <p>
515 こんな感じのテーブルになります。
516 クラス名が <tt>is</tt> フィールドに、メンバ変数はそのままの名前で入ります。
517 配列メンバは cons リストになって入ってきます。
518 </p>
519 ))
520 $(SECTION 微妙な挙動, $(SECBODY
521 <pre>
522 (rawmacro) レイヤの話
523
524 [[limitations]]
525
526 This @macro layer is a very primitive one, and not a perfect macro language.
527 Two major limitations are seen in the following "it" example.
528
529 >> @macro LetItBe(x, y) { let it = x in y };
530
531 The variable name is not hygenic, and so without any effort, the syntax tree "y"
532 can access the outer variable "it".
533
534 >> def foo() { LetItBe( 1+2+3, it*it ) }
535 >> foo()
536 36
537
538 Of course, this is not just a limitation; it can sometimes allow us to write
539 many interesting macros.
540
541 The other problem is that the macro expansion is only done at function startup.
542 So
543
544 >> LetItBe( 1+2+3, it*it )
545 ...\value.d(173): [<REPL>:24:1] variable LetItBe is not set in layer @value
546
547 you cannot directly use the macro in the same scope as the definition.
548 You need to wrap it up in a function (like the foo() in the above example).
549 </pre>
550 ))
551 )
552 ))
553
554
555 $(SECTION Built-in Primitives, $(SECBODY
556 <p>
557 組み込み関数・変数の一覧。
558 </p>
559 $(DDOC_MEMBERS
560
561 $(SECTION テーブル操作, $(SECBODY
562 $(TABLE
563 $(TR $(TH {}) $(TD ()) $(TD 空のテーブルを作る))
564 $(TR $(TH .) $(TD (t, s)) $(TD テーブル t の名前 s のフィールドの値を取得。なければ <tt>undefined</tt>))
565 $(TR $(TH .?) $(TD (t, s)) $(TD テーブル t に名前 s のフィールドがあれば 1、なければ 0))
566 $(TR $(TH .=) $(TD (t, s, v)) $(TD テーブル t を親に持ち、名前 s のフィールドに v が入ったテーブルを作る))
567 )
568 ))
569 <br />
570
571 $(SECTION 制御フロー, $(SECBODY
572 $(TABLE
573 $(TR $(TH if) $(TD (n, ft, fe)) $(TD n が非 0 なら <tt>ft()</t>、0 なら <tt>fe()</tt> を実行))
574 )
575 ))
576 <br />
577
578 $(SECTION 演算, $(SECBODY
579 $(TABLE
580 $(TR $(TH +) $(TD (n, m)) $(TD 整数 n と整数 m を足して返す))
581 $(TR $(TH -) $(TD (n, m)) $(TD 整数の引き算))
582 $(TR $(TH *) $(TD (n, m)) $(TD 整数の掛け算))
583 $(TR $(TH /) $(TD (n, m)) $(TD 整数の割り算))
584 $(TR $(TH %) $(TD (n, m)) $(TD 整数の剰余))
585 $(TR $(TH &&) $(TD (n, m)) $(TD 整数 n と m が両方非 0 なら 1、それ以外では 0))
586 $(TR $(TH ||) $(TD (n, m)) $(TD 整数 n と m がどちらか非 0 なら 1、それ以外では 0))
587 $(TR $(TH ~) $(TD (a, b)) $(TD a と b を文字列化して結合))
588 $(TR $(TH <) $(TD (a, b)) $(TD a と b を比較))
589 $(TR $(TH <=) $(TD (a, b)) $(TD a と b を比較))
590 $(TR $(TH >) $(TD (a, b)) $(TD a と b を比較))
591 $(TR $(TH >=) $(TD (a, b)) $(TD a と b を比較))
592 $(TR $(TH ==) $(TD (a, b)) $(TD a と b を比較))
593 $(TR $(TH !=) $(TD (a, b)) $(TD a と b を比較))
594 )
595 <p>
596 注意点として、作者の趣味の問題で、<tt>&&</tt> と <tt>||</tt> は short-circuit 評価をしません。
597 整数演算の種類が少ないのは、D 言語の std.bigint がビット演算などをサポートしてないためです。
598 文字列が結合しかできないのは、単に手抜きです。
599 </p>
600 ))
601
602 $(SECTION 外部とのやりとり, $(SECBODY
603 $(TABLE
604 $(TR $(TH print) $(TD (a)) $(TD a を文字列化標準出力に改行付きで表示して、a を返す))
605 $(TR $(TH argv) $(TD ) $(TD スクリプトに渡された引数文字列のconsリスト))
606 $(TR $(TH gensym) $(TD ()) $(TD エセgensym。変数名として他とかぶらなそうな文字列を返します))
607 $(TR $(TH rand) $(TD (n)) $(TD 0 以上 n 未満の自然数を31bit以内でランダムに生成します))
608 )
609 ))
610 <br />
611
612 $(SECTION データ型判定, $(SECBODY
613 $(TABLE
614 $(TR $(TH _isint) $(TD (a)) $(TD a が整数なら 1、でなければ 0))
615 $(TR $(TH _isstr) $(TD (a)) $(TD a が文字列なら 1、でなければ 0))
616 $(TR $(TH _isfun) $(TD (a)) $(TD a が関数なら 1、でなければ 0))
617 $(TR $(TH _istable) $(TD (a)) $(TD a がテーブルなら 1、でなければ 0))
618 $(TR $(TH _isundefined) $(TD (a)) $(TD a が未定義値なら 1、でなければ 0))
619 )
620 ))
621 )
622 ))
623
624 )
625 Macros:
626 TITLE=Polemy Reference Manual
627 DOCFILENAME=index.html
628 SECTION=$(DDOC_DECL $(DDOC_PSYMBOL $1)) $(DDOC_DECL_DD $2)
629 SECBODY=$0