OSDN Git Service

first import
[omake-japanese/omake_trans.git] / language.rst
1 .. 4-language
2
3 .. _label4:
4
5 4. OMake言語の概要と文法
6 ==================================
7 プロジェクトは ``OMakefile`` を用いてomakeにどのようにビルドするのか指定しており、文法は ``Makefile`` と似ています。 ``OMakefile`` は3つの文法規則「変数の定義」「関数の定義」「ルールの定義」を持ち合わせています。
8
9 .. index:
10    single: 変数
11 .. _label4.1:
12
13 4.1 変数
14 -------------
15 変数は以下のような文法で定義されます。変数名は任意のアルファベットとアンダースコア ``_`` 、ハイフン ``-`` を用いることができます。 ::
16
17    <name> = <value>
18
19 値にはリテラル文字と展開された変数が束縛できます。変数の展開は ``$(name)`` のような形で表され、 ``<name>`` 変数は現在の環境下において ``<value>`` に置き換わります。いくつかの例を下記に示します。 ::
20
21    CC = gcc
22    CFLAGS = -Wall -g
23    COMMAND = $(CC) $(CFLAGS) -O2
24
25 この例では、 ``COMMAND`` 変数は文字列 ``gcc -Wall -g -O2`` が格納されることとなります。
26
27 ``make(1)`` とは違い、変数の展開は *即座に* 行われ、 *分かりやすい* メカニズムです(詳細はスコーピングのセクションを参照してください)。これはつまり、変数の値は即座に展開され、新しい変数への束縛は古い値に影響されないことを意味しています。例えば、前回の例を下記のような変数の束縛に拡張した場合について考えてみましょう。 ::
28
29    X = $(COMMAND)
30    COMMAND = $(COMMAND) -O3
31    Y = $(COMMAND)
32
33 この例では、変数 ``X`` の値は前回のように文字列 ``gcc -Wall -g -O2`` が格納され、変数 ``Y`` の値は ``gcc -Wall -g -O2 -O3`` となります。
34
35 .. _label4.2:
36
37 4.2 変数に値を追加
38 ---------------------
39 変数はまた、既存の変数に新しい文字列を追加する演算子 ``+=`` を用いることができます。例えば、下記の2つの文は等価です。 ::
40
41    # CLAGS変数にオプションを追加
42    CFLAGS = $(CFLAGS) -Wall -g
43
44    # 上と下の束縛は等価です
45    CFLAGS += -Wall -g
46
47 .. index::
48    single: 配列
49 .. _label4.3:
50
51 4.3 配列
52 ---------------------
53 配列は変数名の後ろに ``[]`` を追加し、初期値を改行を使って要素を指定することで定義できます。各々の行にスペースを入れることは重要です。例えば、下記のコードは文字列 ``c d e`` が出力されます。 ::
54
55     X[] =
56         a b
57         c d e
58         f
59
60     println($(nth 2, $(X)))
61
62 .. index::
63    single: 特殊文字
64    single: クオーティング
65 .. _label4.4:
66
67 4.4 特殊文字とクオート
68 -----------------------
69 文字 ``$():,=#\`` はOMakeの特殊文字に指定されています。これらの文字を普通の文字としてOMakeで扱うためには、バックスラッシュ文字 ``\`` (訳注:日本語環境の場合は円記号 ``¥`` が用いられます)でエスケープする必要があります。 ::
70
71     DOLLAR = \$
72
73 文字列を連結させるために、改行もまたエスケープする必要があります。 ::
74
75     FILES = a.c\
76             b.c\
77             c.c
78
79 バックスラッシュは他の文字でエスケープする必要が *ない* ことに注意してください。よって下記のような例は正常に動作します(これはつまり、文字列中のバックスラッシュが正常に保たれていることを表しています)。 ::
80
81     DOSTARGET = C:\WINDOWS\control.ini
82
83 ある文章をクオーティングしたい場合は ``"#..."`` エスケープを使用します。ダブルクオーテーションの数は任意で、最も外側のクオーテーションは文字列に含まれません。 ::
84
85     A = $""String containing "quoted text" ""
86     B = $"""Multi-line
87         text.
88         The # character is not special"""
89
90 .. index::
91    single: 関数定義
92    single: return
93    single: value
94 .. _label4.5:
95
96 4.5  関数定義
97 ----------------
98 関数は下記のような文法を用いて定義されます。 ::
99
100    <name>(<params>) =
101       <indented-body>
102
103 パラメータは識別させるためにカンマを用いて分割し、中身は関数定義からインデントした状態で、別の行に設置する必要があります。例えば、下記のコードは引数 ``a`` と ``b`` をコロンを用いて結びつける関数について定義しています。 ::
104
105     ColonFun(a, b) =
106         return($(a):$(b))
107
108 ``return`` は関数から値を返す命令文です。 ``return`` 文は必須ではありません。もしこの文が除外された場合、最後に関数が評価した命令文の返り値が返されます。 **注意:** バージョン0.9.6から ``return`` 文は関数を制御する命令文となりましたので、return文が呼ばれた場合、関数はただちに値を返して終了します。 下記の例ではもし引数 ``a`` が ``true`` であった場合、関数 ``f`` はただちにprint文を評価することなく値1を返します。 ::
109
110     f(a) =
111        if $(a)
112           return 1
113        println(The argument is false)
114        return 0
115
116 多くの場合、あなたは関数から直接値を返さずに、セクションやネストされたコードブロックから値を返したいと思うことがあるでしょう。このような場合に、あなたは ``value`` 演算子を使用できます。実際、 ``value`` 演算子は関数だけに限らず、値が必要となった場合はどこでも使用することができます。下記の定義では、変数 ``X`` は ``a`` の値に依存して1か2が束縛され、結果を出力し、関数から値を返します。 ::
117
118     f_value(a) =
119        X =
120           if $(a)
121              value 1
122           else
123              value 2
124        println(The value of X is $(X))
125        value $(X)
126
127 関数はGNU-makeの文法 ``$(<name> <args))`` を用いて呼び出します。 ``<args>`` はカンマで分割された値のリストです。例えば、下記のプログラムでは、変数 ``X`` は値 ``foo:bar`` を含みます。 ::
128
129    X = $(ColonFun foo, bar)
130
131 関数は別に値を含めなくても構わず、普通の関数表記を用いて関数を呼び出すことができます。例えば、以下のプログラムでは文字列“She says: Hello world”を出力します。 ::
132
133     Printer(name) =
134         println($(name) says: Hello world)
135     
136     Printer(She)
137
138 .. index::
139    single: コメント
140 .. _label4.6:
141
142 4.6 コメント
143 ----------------
144 コメントは ``#`` 文字から始まり、行の末尾まで続きます。
145
146 .. index::
147    single: include
148    single: open
149 .. _label4.7:
150
151 4.7 ファイルのインクルード
152 -----------------------------
153 ファイルのインクルードには ``include`` か ``open`` 文を使います。インクルードされたファイルはOMakefileとして、同じ文法で使用できます。 ::
154
155     include $(Config_file)
156
157 ``open`` 文は ``include`` と似ていますが、一回しかインクルードされないのが特徴です。 ::
158
159     open Config
160     
161     # 2回目のopenは無視されますので、
162     # この行はなんの影響も与えません。
163     open Config
164
165 もしファイル名が絶対パスで指定されていない場合、 ``include`` と ``open`` 文の両方は ``OMAKEPATH`` 変数上のパスを探します。 ``open`` 文の場合、この検索は *パースするときに実行される* ので、 ``open`` の引数に他の式を含める必要はありません。
166
167 .. index::
168    single: section
169    single: export
170 .. _label4.8:
171
172 4.8 スコーピング、セクション
173 -------------------------------
174 omakeのスコープはインデントのレベルで定義されます。インデントレベルが上がった場合、omakeでは新しいスコープが導入されます。
175
176 ``section`` 文は新しいスコープを追加したい場合に有効です。例えば、以下のコードは ``X = 2`` を出力した後で、 ``X = 1`` を出力します。 ::
177
178     X = 1
179     section
180         X = 2
181         println(X = $(X))
182
183     println(X = $(X))
184
185 この結果について驚くかもしれませんが─ ``section`` 内での変数の束縛は外部のスコープには影響を及ぼしていないのです。
186
187 6.3で説明する ``export`` 文を使えば、内部スコープの変数をエクスポートすることでこの制限から抜け出すことができます。例えば、もし私たちが前回のサンプルに ``export`` 文を追加した場合、変数 ``X`` の新しい値が返されて、 ``X = 2`` が2回出力されます。 ::
188
189     X = 1
190     section
191         X = 2
192         println(X = $(X))
193         export
194
195     println(X = $(X))
196
197 分離されたスコープが非常に重要な結果を及ぼす場合があります。例えば、各々の ``OMakefile`` はそれ自身のスコープで評価されます。つまり各々のプロジェクトの一部は独立した設定となっているので、一つのOMakefileで変数を定義しても、これは他の ``OMakefile`` の定義に影響を及ぼしません。
198
199 別の例を見てみましょう。異なったビルドターゲットを指定するために、変数を分割するほうが便利である場合を考えます。この場合の頻繁に使う慣用句として、分割されたスコープを定義する ``section`` 文を使用することが挙げられます。 ::
200
201    section
202       CFLAGS += -g
203       %.c: %.y
204           $(YACC) $<
205       .SUBDIRS: foo
206
207    .SUBDIRS: bar baz
208
209 この例では、 ``foo`` サブディレクトリには ``CFLAGS`` 変数に ``-g`` オプションが追加されていますが、 ``bar`` と ``baz`` ディレクトリには追加されていません。この例の場合ですとスコープのルールは非常によく働いており、 ``foo`` サブディレクトリには新しいyaccルールが追加されていますが、 ``bar`` と ``baz`` は追加されていません。さらにいうと、この追加されたルールは現在のディレクトリに影響を及ぼしていません。
210
211 .. index::
212    single: 条件分岐
213    single: if
214 .. _label4.9:
215
216 4.9 条件分岐
217 ----------------
218 トップレベルでの条件分岐は以下のような形となります。 ::
219
220     if <test>
221        <true-clause>
222     elseif <text>
223        <elseif-clause>
224     else
225        <else-clause>
226
227 まず ``<test>`` が評価され、もしそれが *true* の値(真偽値についての詳細は9.2を参照してください)であるならば ``<true-clause>`` 節が評価されます。そうでなければ、残りの節が評価されます。また、 ``if`` 文は複数の ``elseif`` 節を持たせることができます。 ``elseif`` と ``else`` 節はなくても構いません。ただし、新しいスコープを導入するため、それぞれの節はインデントされている必要があります。
228
229 ``if`` 文では、もし評価する文字列が空であったり、内容が ``false`` , ``no`` , ``nil`` , ``undefined`` , ``0`` であった場合、真偽値は *false* として評価されます。それ以外はすべて *true* になります。
230
231 下記の例では典型的な条件分岐の使い方を示しています。 ``OSTYPE`` 変数は現在使っているマシンのアーキテクチャを表しています。 ::
232
233     # アーキテクチャ上での主要な拡張子
234     if $(equal $(OSTYPE), Win32)
235        EXT_LIB = .lib
236        EXT_OBJ = .obj
237        EXT_ASM = .asm
238        EXE = .exe
239        export
240     elseif $(mem $(OSTYPE), Unix Cygwin)
241        EXT_LIB = .a
242        EXT_OBJ = .o
243        EXT_ASM = .s
244        EXE =
245        export
246     else
247        # 他のアーキテクチャの場合は強制終了する
248        eprintln(OS type $(OSTYPE) is not recognized)
249        exit(1)
250
251 .. index::
252    single: switch
253    single: match
254    single: case
255    single: default
256    single: 正規表現
257 .. _label4.10:
258
259 4.10 マッチング
260 -------------------
261 パターンマッチングは ``switch`` と ``match`` 文を使って実現できます。 ::
262
263     switch <string>
264     case <pattern1>
265         <clause1>
266     case <pattern2>
267         <clause2>
268     ...
269     default
270        <default-clause>
271
272 ``case`` の数は任意です。 ``default`` 節はなくても構いませんが、使う場合は一番最後の節で用いるべきです。
273
274 ``switch`` 文での ``<string>`` 文字列は以下の ``<patternN>`` と比較され、適合する節が評価されます。 ::
275
276     switch $(HOST)
277     case mymachine
278         println(Building on mymachine)
279     default
280         println(Building on some other machine)
281
282 ``<patternN>`` は定数である必要はありません。下記の関数は ``pattern1`` のマッチ、そして ``##`` デリミタを用いた ``pattern2`` のマッチを表しています。 ::
283
284    Switch2(s, pattern1, pattern2) =
285       switch $(s)
286       case $(pattern1)
287           println(Pattern1)
288       case $"##$(pattern2)##"
289           println(Pattern2)
290       default
291           println(Neither pattern matched)
292
293 ``match`` の場合、パターンとしてegrep(1)─正規表現─が使用できます。数値変数 ``$1, $2, ...`` は ``\(...\)`` 表現を使って値を取得できます。 ::
294
295     match $(NODENAME)@$(SYSNAME)@$(RELEASE)
296     case $"mymachine.*@\(.*\)@\(.*\)"
297         println(Compiling on mymachine; sysname $1 and release $2 are ignored)
298
299     case $".*@Linux@.*2\.4\.\(.*\)"
300         println(Compiling on a Linux 2.4 system; subrelease is $1)
301
302     default
303         eprintln(Machine configuration not implemented)
304         exit(1)
305
306 .. index::
307    single: オブジェクト
308    single: プロパティ
309    single: メソッド
310 .. _label4.11:
311
312 4.11 オブジェクト
313 ---------------------
314 OMakeはオブジェクト指向言語です。一般的に、オブジェクトはプロパティ(\*)とメソッドを持っています。オブジェクトは変数名の最後に ``.`` を加えることで定義できます。例えば、以下のオブジェクトは2次元平面上での点(1, 5)を表しています。
315
316 (\*訳注: 原文では"fields"となっていましたが、日本ではプロパティが主流なので言い換えました。) ::
317
318     Coord. =
319         x = 1
320         y = 5
321         print(message) =
322            println($"$(message): the point is ($(x), $(y)")
323
324     # Xに5を束縛
325     X = $(Coord.x)
326
327     # これは "Hi: the point is (1, 5)" と出力されます。
328     Coord.print(Hi)
329
330 オブジェクトのプロパティ ``x`` と ``y`` は点の座標を表しています。 ``print`` メソッドは点の現在位置を出力します。
331
332 .. index::
333    single: クラス
334    single: class
335 .. _label4.12:
336
337 4.12 クラス
338 ---------------
339 オブジェクトと同様にして *クラス* も定義できます。例えば、私たちは現在、オブジェクトを生成したり、移動したり、位置を出力するメソッドを持った ``Point`` クラスを作りたいものとしましょう。クラスはオブジェクトの作り方と似ていますが、 ``class`` 文を用いて名前を定義付ける点が違いです。 ::
340
341     Point. =
342         class Point
343
344         # プロパティの通常の値
345         x = 0
346         y = 0
347
348         # 座標から新しいクラスを生成する
349         new(x, y) =
350            this.x = $(x)
351            this.y = $(y)
352            return $(this)
353
354         # 点を右に移動する
355         move-right() =
356            x = $(add $(x), 1)
357            return $(this)
358
359         # 点を出力する
360         print() =
361            println($"The point is ($(x), $(y)")
362
363     p1 = $(Point.new 1, 5)
364     p2 = $(p1.move-right)
365
366     # "The point is (1, 5)" と出力
367     p1.print()
368
369     # "The point is (2, 5)" と出力
370     p2.print()
371
372 変数 ``$(this)`` は現在のオブジェクトを参照していることに注目してください。また、クラスとオブジェクトは新しいオブジェクトを返す ``new`` と ``move-right`` メソッドを持っています。これは、オブジェクト ``p2`` とオブジェクト ``p1`` が別物であり、 ``p1`` はオリジナルの座標(1, 5)を保持していることを表しています。
373
374 .. index::
375    single: 継承
376 .. _label4.13:
377
378 4.13 継承
379 ---------------
380 クラスとオブジェクトは継承(多重継承を含む)を ``extends`` 文によってサポートしています。以下の ``Point3D`` では、 ``x`` , ``y`` , ``z`` プロパティを持ったクラスを定義しています。新しいオブジェクトは、親クラスやオブジェクトが持つすべてのプロパティやメソッドを継承します。 ::
381
382     Z. =
383        z = 0
384
385     Point3D. =
386        extends $(Point)
387        extends $(Z)
388        class Point3D
389
390        print() =
391           println($"The 3D point is ($(x), $(y), $(z))")
392
393     # "new"メソッドはオーバーライドされていませんので、
394     # 下のメソッドは新しく点(1, 5, 0)を返します。
395     p = $(Point3D.new 1, 5)
396
397 .. index::
398    single: static.
399    single: where()
400    single: CheckProg()
401    single: ConfMsgChecking()
402    single: ConfMsgResult()
403 .. _label4.14:
404
405 4.14 static.
406 ---------------
407 ``static.`` オブジェクトはOMakeが動作している間、ずっと一定の値を保持していたい場合に使うオブジェクトです。このオブジェクトはプロジェクトを設定する際に頻繁に用いられます。プロジェクトを設定する変数が何回も書き換えられるのはリスクが高いので、 ``static.`` オブジェクトは設定がちょうど一回だけ行われることを保証してくれます。下記の(どこか冗長な)サンプルでは、 ``static.`` 節がLaTeXコマンドが使用可能であるかどうか調べるために使われています。 ``$(where latex)`` 関数は ``latex`` の絶対パスか、latexコマンドが存在しない場合は ``false`` を返します。 ::
408
409    static. =
410       LATEX_ENABLED = false
411       print(--- Determining if LaTeX is installed )
412       if $(where latex)
413           LATEX_ENABLED = true
414           export
415
416       if $(LATEX_ENABLED)
417          println($'(enabled)')
418       else
419          println($'(disabled)')
420
421 OMakeの標準ライブラリを用いると第14章にあるような ``static.`` をプログラミングするための、多くの有用な関数を試すことができます。標準ライブラリを用いると、上のコードは以下のように書き直せます。 ::
422
423    open configure/Configure
424    static. =
425       LATEX_ENABLED = $(CheckProg latex)
426
427 プロジェクトの設定として使われている ``static.`` 節は、 ``ConfMsgChecking`` や ``ConfMsgResult`` 関数を使って、 ``static.`` 節でどういう動作をしているのかについて出力すべきです(もちろん、標準ライブラリにある多くの関数が、この作業を自動的に行ってくれます)。
428
429 .. index::
430    single: .STATIC
431    single: awk()
432 .. _label4.14.1:
433
434 4.14.1 .STATIC
435 ^^^^^^^^^^^^^^^^^^
436 *この機能はバージョン 0.9.8.5 で搭載されました。*
437
438 ``.STATIC`` 節の書き方は ``static.`` 節の書き方と似ています。文法は以下の3つのどれを選んでも書くことができます。::
439
440     # bodyで定義されたすべての変数をエクスポート
441     .STATIC:
442         <body>
443     
444     # 特にファイル依存を指定したい場合
445     .STATIC: <dependencies>
446         <body>
447     
448     # ファイル依存と同様に、どの変数をエクスポートしたいのか指定する場合
449     .STATIC: <vars>: <dependencies>
450         <body>
451
452 ``<vars>`` は定義する変数名、 ``<dependencies>`` はファイル依存─もし一つのファイルが変更された場合、ルールは再評価される─を指定します。 ``<vars>`` と ``<dependencies>`` はもし必要ならば除外することができ、 ``<body>`` 中で定義されたすべての変数はエクスポートされます。
453
454 たとえば、前回のセクションで示した最後のサンプルは下記のように改良できます。 ::
455
456     open configure/Configure
457     .STATIC:
458         LATEX_ENABLED = $(CheckProg latex)
459
460 印象は ``static.`` ( ``.STATIC`` を使用する代わりに) を使った場合とほとんど似ています。しかしながら、殆どの場合において ``.STATIC`` のほうが優位です。理由は2つあります。
461
462 まず、 ``.STATIC`` 節は遅延評価されます。これはつまり、 ``.STATIC`` 内の変数が一つでも解決されないのならば、評価されることはないということを意味しています。例えばもし ``$(LATEX_ENABLED)`` が決して評価されない変数だとすると、 ``.STATIC`` 節は決して評価されることはありません。これは少なくとも一回はいつでも評価される ``static.`` 節とは対照的です。
463
464 次に、 ``.STATIC`` 節はファイル依存を指定できます。これは、 ``.STATIC`` 節に記憶性を持たせたい場合に有効です。例えば、キーと値のペアを持ったテーブルから辞書を作りたい場合を考えてみましょう。 ``.STATIC`` 節を使うことによって、omakeはこの計算を(omakeが毎回動くときに計算するのではなく)入力されたファイルが変更された場合のみ計算するようにふるまいます。以下の例では、 ``awk`` 関数がファイル ``table-file`` をパースするために用いられています。 ``awk`` 関数は ``key = value`` の形をした行を発見する度に、そのキーと値のペアを ``TABLE`` 変数に追加します。 ::
465
466     .STATIC: table-file
467         TABLE = $(Map)
468         awk(table-file)
469         case $'^\([[:alnum:]]+\) *= *\(.*\)'
470             TABLE = $(TABLE.add $1, $2)
471             export
472
473 ルールの依存関係が変わった場合はいつでも ``.STATIC`` 節は再計算されます。このルール内での対象は、エクスポートする変数となります(この場合ですと ``TABLE`` 変数が相当します)。
474
475 .. index::
476    single: .MEMO
477 .. _label4.14.1.1:
478
479 4.14.1.1  .MEMO
480 """"""""""""""""""
481 ``.MEMO`` ルールは、その結果が独立して動いている ``omake`` インスタンス間で保存されない点を除いて、 ``.STATIC`` ルールと等価です。
482
483 .. index::
484    single: :key:
485    single: .MEMO
486    single: 再帰関数
487 .. _label4.14.1.2:
488
489 4.14.1.2  :key:
490 """"""""""""""""""
491 ``.STATIC`` と ``.MEMO`` ルールはまた、計算された値とリンクしている「キー」を表す ``:key:`` を使うことができます。 ``.STATIC`` ルールを、キーと値がリンクした辞書として考えることは有用です。 ``.STATIC`` ルールが評価された場合、結果は指定されたルールによって定義された ``:key:`` がテーブル内に保存されます(もし ``:key:`` が指定されていない場合、デフォルトのキーが代わりに用いられます)。言い換えると、ルールは関数のようなものです。 ``:key:`` は関数の「引数」を表しており、ルール部分で結果を計算します。
492
493 これを確かめるために、 ``.MEMO`` ルールをフィボナッチ関数に改良してみましょう。 ::
494
495     fib(i) =
496         i = $(int $i)
497         .MEMO: :key: $i
498             println($"Computing fib($i)...")
499             result =
500                 if $(or $(eq $i, 0), $(eq $i, 1))
501                     value $i
502                 else
503                     add($(fib $(sub $i, 1)), $(fib $(sub $i, 2)))
504         value $(result)
505     
506     println($"fib(10) = $(fib 10)")
507     println($"fib(12) = $(fib 12)")
508
509 このスクリプトを走らせた場合、以下のような結果となります。 ::
510
511     Computing fib(10)...
512     Computing fib(9)...
513     Computing fib(8)...
514     Computing fib(7)...
515     Computing fib(6)...
516     Computing fib(5)...
517     Computing fib(4)...
518     Computing fib(3)...
519     Computing fib(2)...
520     Computing fib(1)...
521     Computing fib(0)...
522     fib(10) = 55
523     Computing fib(12)...
524     Computing fib(11)...
525     fib(12) = 144
526
527 フィボナッチ関数は各々の引数の場合において、一回だけしか計算されていないことに注目してください。これは普通にプログラムした場合ですと、指数関数的に計算時間が増えてしまいます。言い換えると、 ``.MEMO`` ルールは計算結果を記憶(memoization)しているからこそ、この名前なのです。もし ``.STATIC`` ルールを代わりに使った場合、すべての ``omake`` インスタンスにおいて値が保存されていることに注意してください。
528
529 一般的には、あなたは ``.STATIC`` か ``.MEMO`` ルールを関数内で用いる場合はいつでも、ふつう ``:key:`` を使いたくなるでしょう。しかしながら、これは必須ではありません。以下の例では、 ``.STATIC`` ルールが、何か計算時間のかかる作業を一回だけ行う場合を表しています。 ::
530
531     f(x) =
532         .STATIC:
533             y = $(expensive-computation)
534         add($x, $y)
535
536 あなたがフィボナッチ関数のような再帰的な関数を定義する場合、さらに以下の点に注意すべきです。もし ``:key:`` を除外してしまった場合、ルールは関数自体に対して定義されてしまい、循環された依存関係で評価されてしまいます。以下は ``:key:`` を除いたフィボナッチ関数の出力結果です。 ::
537
538     Computing fib(10)...
539     Computing fib(8)...
540     Computing fib(6)...
541     Computing fib(4)...
542     Computing fib(2)...
543     Computing fib(0)...
544     fib(10) = 0
545     fib(12) = 0
546
547 この動作は ``i = 0 || i = 1`` の場合に達するまで ``result`` の値が保存されていないので、 ``fib`` は自身を ``fib(0)`` に達するまで再帰的に呼び出し、そして ``result`` の値は0に修正されてしまうために生じます。
548
549 再帰的な定義が無難に動作する場合もありますが、あなたは普通 ``:key:`` 引数をつけることで、各々の再帰的な呼び出しが異なった ``:key:`` を持つようにするでしょう。これは多くの場合において、 ``:key:`` が関数の引数すべてに含めるべきであることを示しています。
550
551 .. index::
552    single: 整数型
553    single: 浮動小数点型
554    single: 配列
555    single: 文字列
556    single: ファイル
557    single: ディレクトリ
558    single: マップ
559    single: 辞書
560    single: チャネル
561    single: 関数
562    single: 無名関数
563    single: 字句解析
564    single: パーサ
565 .. _label4.15:
566
567 4.15 定数
568 -----------------
569 OMakeではいろんな方法でそれぞれの値を表すことができます。私たちはこれを以下のリストにしました。
570
571 * int - 整数型
572
573   * コンストラクタ: ``$(int <i>)`` 9.4.1
574   * オブジェクト: ``Int`` 12.1.4
575   * 有限の値をもった整数型で、精度はプラットフォーム上のOCamlに依存します(32ビットのプラットフォーム上では31ビット、64ビットのプラットフォーム上では63ビット)(訳注: 1ビットは正負の判定に使われます)。
576   * 詳細は9.4.3の「算術」を参照してください。
577
578 * float - 浮動小数点型
579
580   * コンストラクタ: ``$(float <x>)`` 9.4.2
581   * オブジェクト: ``Float`` 12.1.5
582   * 浮動小数点型で、精度は64ビットです。
583
584 * array - 配列
585
586   * コンストラクタ: ``$(array <v1>, ..., <vn>)`` 9.3.1
587   * オブジェクト: ``Array`` 12.1.7
588   * 配列は有限の数の値をもったリストを表します。配列はまた以下のように定義することもできます。 ::
589     
590         X[] =
591             <v1>
592             ...
593             <vn>
594   
595   * 詳細は ``nth`` 9.3.5, ``nth-tl`` 9.3.8, ``length`` 9.3.4を参照してください。
596
597 * string - 文字列
598
599   * オブジェクト: ``String`` 12.1.8
600   * 通常、すべての文字からなるシーケンスは配列として表現され、単純にソース中に書き表すことで初期化できます。内部で文字列はいくつかの断片としてパースされます。文字列はしばしば、ホワイトスペース(訳注: ホワイトスペースはスペース、タブを含んだ空白文字のことです)によって分割された値のシーケンスとして定義されます。 ::
601
602       osh>S = This is a string
603       - : <sequence
604          "This" : Sequence
605          ' ' : White
606          "is" : Sequence
607          ' ' : White
608          "a" : Sequence
609          ' ' : White
610          "string" : Sequence>
611          : Sequence
612       osh>length($S)
613       - : 4 : Int
614
615   * *データ* 文字列は、ホワイトスペースが重要な意味を持つ場合に用いられます。これは単純な一つの値として定義され、配列にはなりません。コンストラクタはクオーテーション ``$"..."`` と ``$'...'`` で表現できます。 ::
616
617       osh>S = $'''This is a string'''
618       - : <data "This is a string"> : String
619
620   * 詳細は「 :ref:`label7.2` 」を参照してください。
621
622 * file - ファイル
623
624   * コンストラクタ: ``$(file <names>)`` 10.1.1
625   * オブジェクト: ``File`` 12.1.13
626   * ファイルオブジェクトはファイルの絶対パスを表すオブジェクトです。ファイルオブジェクトは絶対パスとして見ることができます。文字列への変換はカレントディレクトリに依存しています。 ::
627
628       osh>name = $(file foo)
629       - : /Users/jyh/projects/omake/0.9.8.x/foo : File
630       osh>echo $(name)
631       foo
632       osh>cd ..
633       - : /Users/jyh/projects/omake : Dir
634       osh>echo $(name)
635       0.9.8.x/foo
636
637   * 詳細は ``vmount`` 10.6.1を参照してください。
638
639 * directory - ディレクトリ
640
641   * コンストラクタ: ``$(dir <names>)``
642   * オブジェクト: ``Dir`` 12.1.14
643   * ディレクトリオブジェクトはファイルオブジェクトと似ていますが、ディレクトリとしてふるまいます。
644
645 * map (dictionary) - マップ (辞書)
646
647   * オブジェクト: ``Map`` 12.1.2
648   * マップ/辞書オブジェクトは値と値を結びつけるテーブルです。 ``Map`` オブジェクトは空のマップです。データ構造は永続的に保持され、すべての演算は分かりやすく関数的です。特別な構文 ``$|key|`` によって文字列のキーを表現することができます。 ::
649
650       osh>table = $(Map)
651       osh>table = $(table.add x, int)
652       osh>table. +=
653               $|y| = int
654       osh>table.find(y)
655       - : "int" : Sequence
656
657 * channel - チャネル
658
659   * コンストラクタ: ``$(fopen <filename>, <mode>)`` 10.8.4
660   * オブジェクト: ``InChannel`` 12.1.16, ``OutChannnel`` 12.1.17
661   * チャネルオブジェクトは入力や出力のバッファとして使います。
662
663 * function - 関数
664
665   * コンストラクタ: ``$(fun <params>, <body>)`` 9.5.1
666   * オブジェクト: ``Fun`` 12.1.9
667   * 関数オブジェクトはいろんな方法で定義できます。
668
669     * 無名関数 ::
670
671         $(fun i, j, $(add $i, $j))
672
673     * 名前をつけた関数 ::
674
675         f(i, j) =
676             add($i, $j)
677
678     * *この機能はバージョン0.9.9.0で導入されました。* 無名関数の引数 ::
679
680         osh>foreach(i => $(add $i, 1), 1 2 3)
681         - : <array 2 3 4> : Array
682
683 * lexer - 字句解析
684
685   * オブジェクト: ``Lexer`` 10.11.9
686   * このオブジェクトは字句解析器として表現します。
687
688 * parser - パーサ
689
690   * オブジェクト: ``Parser`` 10.11.13
691   * このオブジェクトはパーサとして表現します。