OSDN Git Service

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