.. 4-language .. _label4: 4. OMake言語の概要と文法 ================================== プロジェクトは ``OMakefile`` を用いてomakeにどのようにビルドするのか指定しており、文法は ``Makefile`` と似ています。 ``OMakefile`` は3つの文法規則「変数の定義」「関数の定義」「ルールの定義」を持ち合わせています。 .. index: single: 変数 .. _label4.1: 4.1 変数 ------------- 変数は以下のような文法で定義されます。変数名は任意のアルファベットとアンダースコア ``_`` 、ハイフン ``-`` を用いることができます。 :: = 値にはリテラル文字と展開された変数が束縛できます。変数の展開は ``$(name)`` のような形で表され、 ```` 変数は現在の環境下において ```` に置き換わります。いくつかの例を下記に示します。 :: CC = gcc CFLAGS = -Wall -g COMMAND = $(CC) $(CFLAGS) -O2 この例では、 ``COMMAND`` 変数は文字列 ``gcc -Wall -g -O2`` が格納されることとなります。 ``make(1)`` とは違い、変数の展開は *即座に* 行われ、 *分かりやすい* メカニズムです(詳細はスコーピングのセクションを参照してください)。これはつまり、変数の値は即座に展開され、新しい変数への束縛は古い値に影響されないことを意味しています。例えば、前回の例を下記のような変数の束縛に拡張した場合について考えてみましょう。 :: X = $(COMMAND) COMMAND = $(COMMAND) -O3 Y = $(COMMAND) この例では、変数 ``X`` の値は前回のように文字列 ``gcc -Wall -g -O2`` が格納され、変数 ``Y`` の値は ``gcc -Wall -g -O2 -O3`` となります。 .. _label4.2: 4.2 変数に値を追加 --------------------- 変数はまた、既存の変数に新しい文字列を追加する演算子 ``+=`` を用いることができます。例えば、下記の2つの文は等価です。 :: # CLAGS変数にオプションを追加 CFLAGS = $(CFLAGS) -Wall -g # 上と下の束縛は等価です CFLAGS += -Wall -g .. index:: single: 配列 .. _label4.3: 4.3 配列 --------------------- 配列は変数名の後ろに ``[]`` を追加し、初期値を改行を使って要素を指定することで定義できます。各々の行にスペースを入れることは重要です。例えば、下記のコードは文字列 ``c d e`` が出力されます。 :: X[] = a b c d e f println($(nth 2, $(X))) .. index:: single: 特殊文字 single: クオーティング .. _label4.4: 4.4 特殊文字とクオート ----------------------- 文字 ``$():,=#\`` はOMakeの特殊文字に指定されています。これらの文字を普通の文字としてOMakeで扱うためには、バックスラッシュ文字 ``\`` (訳注:日本語環境の場合は円記号 ``¥`` が用いられます)でエスケープする必要があります。 :: DOLLAR = \$ 文字列を連結させるために、改行もまたエスケープする必要があります。 :: FILES = a.c\ b.c\ c.c バックスラッシュは他の文字でエスケープする必要が *ない* ことに注意してください。よって下記のような例は正常に動作します(これはつまり、文字列中のバックスラッシュが正常に保たれていることを表しています)。 :: DOSTARGET = C:\WINDOWS\control.ini ある文章をクオーティングしたい場合は ``"#..."`` エスケープを使用します。ダブルクオーテーションの数は任意で、最も外側のクオーテーションは文字列に含まれません。 :: A = $""String containing "quoted text" "" B = $"""Multi-line text. The # character is not special""" .. index:: single: 関数定義 single: return single: value .. _label4.5: 4.5 関数定義 ---------------- 関数は下記のような文法を用いて定義されます。 :: () = パラメータは識別させるためにカンマを用いて分割し、中身は関数定義からインデントした状態で、別の行に設置する必要があります。例えば、下記のコードは引数 ``a`` と ``b`` をコロンを用いて結びつける関数について定義しています。 :: ColonFun(a, b) = return($(a):$(b)) ``return`` は関数から値を返す命令文です。 ``return`` 文は必須ではありません。もしこの文が除外された場合、最後に関数が評価した命令文の返り値が返されます。 **注意:** バージョン0.9.6から ``return`` 文は関数を制御する命令文となりましたので、return文が呼ばれた場合、関数はただちに値を返して終了します。 下記の例ではもし引数 ``a`` が ``true`` であった場合、関数 ``f`` はただちにprint文を評価することなく値1を返します。 :: f(a) = if $(a) return 1 println(The argument is false) return 0 多くの場合、あなたは関数から直接値を返さずに、セクションやネストされたコードブロックから値を返したいと思うことがあるでしょう。このような場合に、あなたは ``value`` 演算子を使用できます。実際、 ``value`` 演算子は関数だけに限らず、値が必要となった場合はどこでも使用することができます。下記の定義では、変数 ``X`` は ``a`` の値に依存して1か2が束縛され、結果を出力し、関数から値を返します。 :: f_value(a) = X = if $(a) value 1 else value 2 println(The value of X is $(X)) value $(X) 関数はGNU-makeの文法 ``$( `` はカンマで分割された値のリストです。例えば、下記のプログラムでは、変数 ``X`` は値 ``foo:bar`` を含みます。 :: X = $(ColonFun foo, bar) 関数は別に値を含めなくても構わず、普通の関数表記を用いて関数を呼び出すことができます。例えば、以下のプログラムでは文字列“She says: Hello world”を出力します。 :: Printer(name) = println($(name) says: Hello world) Printer(She) .. index:: single: コメント .. _label4.6: 4.6 コメント ---------------- コメントは ``#`` 文字から始まり、行の末尾まで続きます。 .. index:: single: include single: open .. _label4.7: 4.7 ファイルのインクルード ----------------------------- ファイルのインクルードには ``include`` か ``open`` 文を使います。インクルードされたファイルはOMakefileとして、同じ文法で使用できます。 :: include $(Config_file) ``open`` 文は ``include`` と似ていますが、一回しかインクルードされないのが特徴です。 :: open Config # 2回目のopenは無視されますので、 # この行はなんの影響も与えません。 open Config もしファイル名が絶対パスで指定されていない場合、 ``include`` と ``open`` 文の両方は ``OMAKEPATH`` 変数上のパスを探します。 ``open`` 文の場合、この検索は *パースするときに実行される* ので、 ``open`` の引数に他の式を含める必要はありません。 .. index:: single: section single: export .. _label4.8: 4.8 スコーピング、セクション ------------------------------- omakeのスコープはインデントのレベルで定義されます。インデントレベルが上がった場合、omakeでは新しいスコープが導入されます。 ``section`` 文は新しいスコープを追加したい場合に有効です。例えば、以下のコードは ``X = 2`` を出力した後で、 ``X = 1`` を出力します。 :: X = 1 section X = 2 println(X = $(X)) println(X = $(X)) この結果について驚くかもしれませんが─ ``section`` 内での変数の束縛は外部のスコープには影響を及ぼしていないのです。 6.3で説明する ``export`` 文を使えば、内部スコープの変数をエクスポートすることでこの制限から抜け出すことができます。例えば、もし私たちが前回のサンプルに ``export`` 文を追加した場合、変数 ``X`` の新しい値が返されて、 ``X = 2`` が2回出力されます。 :: X = 1 section X = 2 println(X = $(X)) export println(X = $(X)) 分離されたスコープが非常に重要な結果を及ぼす場合があります。例えば、各々の ``OMakefile`` はそれ自身のスコープで評価されます。つまり各々のプロジェクトの一部は独立した設定となっているので、一つのOMakefileで変数を定義しても、これは他の ``OMakefile`` の定義に影響を及ぼしません。 別の例を見てみましょう。異なったビルドターゲットを指定するために、変数を分割するほうが便利である場合を考えます。この場合の頻繁に使う慣用句として、分割されたスコープを定義する ``section`` 文を使用することが挙げられます。 :: section CFLAGS += -g %.c: %.y $(YACC) $< .SUBDIRS: foo .SUBDIRS: bar baz この例では、 ``foo`` サブディレクトリには ``CFLAGS`` 変数に ``-g`` オプションが追加されていますが、 ``bar`` と ``baz`` ディレクトリには追加されていません。この例の場合ですとスコープのルールは非常によく働いており、 ``foo`` サブディレクトリには新しいyaccルールが追加されていますが、 ``bar`` と ``baz`` は追加されていません。さらにいうと、この追加されたルールは現在のディレクトリに影響を及ぼしていません。 .. index:: single: 条件分岐 single: if .. _label4.9: 4.9 条件分岐 ---------------- トップレベルでの条件分岐は以下のような形となります。 :: if elseif else まず ```` が評価され、もしそれが *true* の値(真偽値についての詳細は9.2を参照してください)であるならば ```` 節が評価されます。そうでなければ、残りの節が評価されます。また、 ``if`` 文は複数の ``elseif`` 節を持たせることができます。 ``elseif`` と ``else`` 節はなくても構いません。ただし、新しいスコープを導入するため、それぞれの節はインデントされている必要があります。 ``if`` 文では、もし評価する文字列が空であったり、内容が ``false`` , ``no`` , ``nil`` , ``undefined`` , ``0`` であった場合、真偽値は *false* として評価されます。それ以外はすべて *true* になります。 下記の例では典型的な条件分岐の使い方を示しています。 ``OSTYPE`` 変数は現在使っているマシンのアーキテクチャを表しています。 :: # アーキテクチャ上での主要な拡張子 if $(equal $(OSTYPE), Win32) EXT_LIB = .lib EXT_OBJ = .obj EXT_ASM = .asm EXE = .exe export elseif $(mem $(OSTYPE), Unix Cygwin) EXT_LIB = .a EXT_OBJ = .o EXT_ASM = .s EXE = export else # 他のアーキテクチャの場合は強制終了する eprintln(OS type $(OSTYPE) is not recognized) exit(1) .. index:: single: switch single: match single: case single: default single: 正規表現 .. _label4.10: 4.10 マッチング ------------------- パターンマッチングは ``switch`` と ``match`` 文を使って実現できます。 :: switch case case ... default ``case`` の数は任意です。 ``default`` 節はなくても構いませんが、使う場合は一番最後の節で用いるべきです。 ``switch`` 文での ```` 文字列は以下の ```` と比較され、適合する節が評価されます。 :: switch $(HOST) case mymachine println(Building on mymachine) default println(Building on some other machine) ```` は定数である必要はありません。下記の関数は ``pattern1`` のマッチ、そして ``##`` デリミタを用いた ``pattern2`` のマッチを表しています。 :: Switch2(s, pattern1, pattern2) = switch $(s) case $(pattern1) println(Pattern1) case $"##$(pattern2)##" println(Pattern2) default println(Neither pattern matched) ``match`` の場合、パターンとしてegrep(1)─正規表現─が使用できます。数値変数 ``$1, $2, ...`` は ``\(...\)`` 表現を使って値を取得できます。 :: match $(NODENAME)@$(SYSNAME)@$(RELEASE) case $"mymachine.*@\(.*\)@\(.*\)" println(Compiling on mymachine; sysname $1 and release $2 are ignored) case $".*@Linux@.*2\.4\.\(.*\)" println(Compiling on a Linux 2.4 system; subrelease is $1) default eprintln(Machine configuration not implemented) exit(1) .. index:: single: オブジェクト single: プロパティ single: メソッド .. _label4.11: 4.11 オブジェクト --------------------- OMakeはオブジェクト指向言語です。一般的に、オブジェクトはプロパティ(\*)とメソッドを持っています。オブジェクトは変数名の最後に ``.`` を加えることで定義できます。例えば、以下のオブジェクトは2次元平面上での点(1, 5)を表しています。 (\*訳注: 原文では"fields"となっていましたが、日本ではプロパティが主流なので言い換えました。) :: Coord. = x = 1 y = 5 print(message) = println($"$(message): the point is ($(x), $(y)") # Xに5を束縛 X = $(Coord.x) # これは "Hi: the point is (1, 5)" と出力されます。 Coord.print(Hi) オブジェクトのプロパティ ``x`` と ``y`` は点の座標を表しています。 ``print`` メソッドは点の現在位置を出力します。 .. index:: single: クラス single: class .. _label4.12: 4.12 クラス --------------- オブジェクトと同様にして *クラス* も定義できます。例えば、私たちは現在、オブジェクトを生成したり、移動したり、位置を出力するメソッドを持った ``Point`` クラスを作りたいものとしましょう。クラスはオブジェクトの作り方と似ていますが、 ``class`` 文を用いて名前を定義付ける点が違いです。 :: Point. = class Point # プロパティの通常の値 x = 0 y = 0 # 座標から新しいクラスを生成する new(x, y) = this.x = $(x) this.y = $(y) return $(this) # 点を右に移動する move-right() = x = $(add $(x), 1) return $(this) # 点を出力する print() = println($"The point is ($(x), $(y)") p1 = $(Point.new 1, 5) p2 = $(p1.move-right) # "The point is (1, 5)" と出力 p1.print() # "The point is (2, 5)" と出力 p2.print() 変数 ``$(this)`` は現在のオブジェクトを参照していることに注目してください。また、クラスとオブジェクトは新しいオブジェクトを返す ``new`` と ``move-right`` メソッドを持っています。これは、オブジェクト ``p2`` とオブジェクト ``p1`` が別物であり、 ``p1`` はオリジナルの座標(1, 5)を保持していることを表しています。 .. index:: single: 継承 .. _label4.13: 4.13 継承 --------------- クラスとオブジェクトは継承(多重継承を含む)を ``extends`` 文によってサポートしています。以下の ``Point3D`` では、 ``x`` , ``y`` , ``z`` プロパティを持ったクラスを定義しています。新しいオブジェクトは、親クラスやオブジェクトが持つすべてのプロパティやメソッドを継承します。 :: Z. = z = 0 Point3D. = extends $(Point) extends $(Z) class Point3D print() = println($"The 3D point is ($(x), $(y), $(z))") # "new"メソッドはオーバーライドされていませんので、 # 下のメソッドは新しく点(1, 5, 0)を返します。 p = $(Point3D.new 1, 5) .. index:: single: static. single: where() single: CheckProg() single: ConfMsgChecking() single: ConfMsgResult() .. _label4.14: 4.14 static. --------------- ``static.`` オブジェクトはOMakeが動作している間、ずっと一定の値を保持していたい場合に使うオブジェクトです。このオブジェクトはプロジェクトを設定する際に頻繁に用いられます。プロジェクトを設定する変数が何回も書き換えられるのはリスクが高いので、 ``static.`` オブジェクトは設定がちょうど一回だけ行われることを保証してくれます。下記の(どこか冗長な)サンプルでは、 ``static.`` 節がLaTeXコマンドが使用可能であるかどうか調べるために使われています。 ``$(where latex)`` 関数は ``latex`` の絶対パスか、latexコマンドが存在しない場合は ``false`` を返します。 :: static. = LATEX_ENABLED = false print(--- Determining if LaTeX is installed ) if $(where latex) LATEX_ENABLED = true export if $(LATEX_ENABLED) println($'(enabled)') else println($'(disabled)') OMakeの標準ライブラリを用いると第14章にあるような ``static.`` をプログラミングするための、多くの有用な関数を試すことができます。標準ライブラリを用いると、上のコードは以下のように書き直せます。 :: open configure/Configure static. = LATEX_ENABLED = $(CheckProg latex) プロジェクトの設定として使われている ``static.`` 節は、 ``ConfMsgChecking`` や ``ConfMsgResult`` 関数を使って、 ``static.`` 節でどういう動作をしているのかについて出力すべきです(もちろん、標準ライブラリにある多くの関数が、この作業を自動的に行ってくれます)。 .. index:: single: .STATIC single: awk() .. _label4.14.1: 4.14.1 .STATIC ^^^^^^^^^^^^^^^^^^ *この機能はバージョン 0.9.8.5 で搭載されました。* ``.STATIC`` 節の書き方は ``static.`` 節の書き方と似ています。文法は以下の3つのどれを選んでも書くことができます。:: # bodyで定義されたすべての変数をエクスポート .STATIC: # 特にファイル依存を指定したい場合 .STATIC: # ファイル依存と同様に、どの変数をエクスポートしたいのか指定する場合 .STATIC: : ```` は定義する変数名、 ```` はファイル依存─もし一つのファイルが変更された場合、ルールは再評価される─を指定します。 ```` と ```` はもし必要ならば除外することができ、 ```` 中で定義されたすべての変数はエクスポートされます。 たとえば、前回のセクションで示した最後のサンプルは下記のように改良できます。 :: open configure/Configure .STATIC: LATEX_ENABLED = $(CheckProg latex) 印象は ``static.`` ( ``.STATIC`` を使用する代わりに) を使った場合とほとんど似ています。しかしながら、殆どの場合において ``.STATIC`` のほうが優位です。理由は2つあります。 まず、 ``.STATIC`` 節は遅延評価されます。これはつまり、 ``.STATIC`` 内の変数が一つでも解決されないのならば、評価されることはないということを意味しています。例えばもし ``$(LATEX_ENABLED)`` が決して評価されない変数だとすると、 ``.STATIC`` 節は決して評価されることはありません。これは少なくとも一回はいつでも評価される ``static.`` 節とは対照的です。 次に、 ``.STATIC`` 節はファイル依存を指定できます。これは、 ``.STATIC`` 節に記憶性を持たせたい場合に有効です。例えば、キーと値のペアを持ったテーブルから辞書を作りたい場合を考えてみましょう。 ``.STATIC`` 節を使うことによって、omakeはこの計算を(omakeが毎回動くときに計算するのではなく)入力されたファイルが変更された場合のみ計算するようにふるまいます。以下の例では、 ``awk`` 関数がファイル ``table-file`` をパースするために用いられています。 ``awk`` 関数は ``key = value`` の形をした行を発見する度に、そのキーと値のペアを ``TABLE`` 変数に追加します。 :: .STATIC: table-file TABLE = $(Map) awk(table-file) case $'^\([[:alnum:]]+\) *= *\(.*\)' TABLE = $(TABLE.add $1, $2) export ルールの依存関係が変わった場合はいつでも ``.STATIC`` 節は再計算されます。このルール内での対象は、エクスポートする変数となります(この場合ですと ``TABLE`` 変数が相当します)。 .. index:: single: .MEMO .. _label4.14.1.1: 4.14.1.1 .MEMO """""""""""""""""" ``.MEMO`` ルールは、その結果が独立して動いている ``omake`` インスタンス間で保存されない点を除いて、 ``.STATIC`` ルールと等価です。 .. index:: single: :key: single: .MEMO single: 再帰関数 .. _label4.14.1.2: 4.14.1.2 :key: """""""""""""""""" ``.STATIC`` と ``.MEMO`` ルールはまた、計算された値とリンクしている「キー」を表す ``:key:`` を使うことができます。 ``.STATIC`` ルールを、キーと値がリンクした辞書として考えることは有用です。 ``.STATIC`` ルールが評価された場合、結果は指定されたルールによって定義された ``:key:`` がテーブル内に保存されます(もし ``:key:`` が指定されていない場合、デフォルトのキーが代わりに用いられます)。言い換えると、ルールは関数のようなものです。 ``:key:`` は関数の「引数」を表しており、ルール部分で結果を計算します。 これを確かめるために、 ``.MEMO`` ルールをフィボナッチ関数に改良してみましょう。 :: fib(i) = i = $(int $i) .MEMO: :key: $i println($"Computing fib($i)...") result = if $(or $(eq $i, 0), $(eq $i, 1)) value $i else add($(fib $(sub $i, 1)), $(fib $(sub $i, 2))) value $(result) println($"fib(10) = $(fib 10)") println($"fib(12) = $(fib 12)") このスクリプトを走らせた場合、以下のような結果となります。 :: Computing fib(10)... Computing fib(9)... Computing fib(8)... Computing fib(7)... Computing fib(6)... Computing fib(5)... Computing fib(4)... Computing fib(3)... Computing fib(2)... Computing fib(1)... Computing fib(0)... fib(10) = 55 Computing fib(12)... Computing fib(11)... fib(12) = 144 フィボナッチ関数は各々の引数の場合において、一回だけしか計算されていないことに注目してください。これは普通にプログラムした場合ですと、指数関数的に計算時間が増えてしまいます。言い換えると、 ``.MEMO`` ルールは計算結果を記憶(memoization)しているからこそ、この名前なのです。もし ``.STATIC`` ルールを代わりに使った場合、すべての ``omake`` インスタンスにおいて値が保存されていることに注意してください。 一般的には、あなたは ``.STATIC`` か ``.MEMO`` ルールを関数内で用いる場合はいつでも、ふつう ``:key:`` を使いたくなるでしょう。しかしながら、これは必須ではありません。以下の例では、 ``.STATIC`` ルールが、何か計算時間のかかる作業を一回だけ行う場合を表しています。 :: f(x) = .STATIC: y = $(expensive-computation) add($x, $y) あなたがフィボナッチ関数のような再帰的な関数を定義する場合、さらに以下の点に注意すべきです。もし ``:key:`` を除外してしまった場合、ルールは関数自体に対して定義されてしまい、循環された依存関係で評価されてしまいます。以下は ``:key:`` を除いたフィボナッチ関数の出力結果です。 :: Computing fib(10)... Computing fib(8)... Computing fib(6)... Computing fib(4)... Computing fib(2)... Computing fib(0)... fib(10) = 0 fib(12) = 0 この動作は ``i = 0 || i = 1`` の場合に達するまで ``result`` の値が保存されていないので、 ``fib`` は自身を ``fib(0)`` に達するまで再帰的に呼び出し、そして ``result`` の値は0に修正されてしまうために生じます。 再帰的な定義が無難に動作する場合もありますが、あなたは普通 ``:key:`` 引数をつけることで、各々の再帰的な呼び出しが異なった ``:key:`` を持つようにするでしょう。これは多くの場合において、 ``:key:`` が関数の引数すべてに含めるべきであることを示しています。 .. index:: single: 整数型 single: 浮動小数点型 single: 配列 single: 文字列 single: ファイル single: ディレクトリ single: マップ single: 辞書 single: チャネル single: 関数 single: 無名関数 single: 字句解析 single: パーサ .. _label4.15: 4.15 定数 ----------------- OMakeではいろんな方法でそれぞれの値を表すことができます。私たちはこれを以下のリストにしました。 * int - 整数型 * コンストラクタ: ``$(int )`` 9.4.1 * オブジェクト: ``Int`` 12.1.4 * 有限の値をもった整数型で、精度はプラットフォーム上のOCamlに依存します(32ビットのプラットフォーム上では31ビット、64ビットのプラットフォーム上では63ビット)(訳注: 1ビットは正負の判定に使われます)。 * 詳細は9.4.3の「算術」を参照してください。 * float - 浮動小数点型 * コンストラクタ: ``$(float )`` 9.4.2 * オブジェクト: ``Float`` 12.1.5 * 浮動小数点型で、精度は64ビットです。 * array - 配列 * コンストラクタ: ``$(array , ..., )`` 9.3.1 * オブジェクト: ``Array`` 12.1.7 * 配列は有限の数の値をもったリストを表します。配列はまた以下のように定義することもできます。 :: X[] = ... * 詳細は ``nth`` 9.3.5, ``nth-tl`` 9.3.8, ``length`` 9.3.4を参照してください。 * string - 文字列 * オブジェクト: ``String`` 12.1.8 * 通常、すべての文字からなるシーケンスは配列として表現され、単純にソース中に書き表すことで初期化できます。内部で文字列はいくつかの断片としてパースされます。文字列はしばしば、ホワイトスペース(訳注: ホワイトスペースはスペース、タブを含んだ空白文字のことです)によって分割された値のシーケンスとして定義されます。 :: osh>S = This is a string - : : Sequence osh>length($S) - : 4 : Int * *データ* 文字列は、ホワイトスペースが重要な意味を持つ場合に用いられます。これは単純な一つの値として定義され、配列にはなりません。コンストラクタはクオーテーション ``$"..."`` と ``$'...'`` で表現できます。 :: osh>S = $'''This is a string''' - : : String * 詳細は「 :ref:`label7.2` 」を参照してください。 * file - ファイル * コンストラクタ: ``$(file )`` 10.1.1 * オブジェクト: ``File`` 12.1.13 * ファイルオブジェクトはファイルの絶対パスを表すオブジェクトです。ファイルオブジェクトは絶対パスとして見ることができます。文字列への変換はカレントディレクトリに依存しています。 :: osh>name = $(file foo) - : /Users/jyh/projects/omake/0.9.8.x/foo : File osh>echo $(name) foo osh>cd .. - : /Users/jyh/projects/omake : Dir osh>echo $(name) 0.9.8.x/foo * 詳細は ``vmount`` 10.6.1を参照してください。 * directory - ディレクトリ * コンストラクタ: ``$(dir )`` * オブジェクト: ``Dir`` 12.1.14 * ディレクトリオブジェクトはファイルオブジェクトと似ていますが、ディレクトリとしてふるまいます。 * map (dictionary) - マップ (辞書) * オブジェクト: ``Map`` 12.1.2 * マップ/辞書オブジェクトは値と値を結びつけるテーブルです。 ``Map`` オブジェクトは空のマップです。データ構造は永続的に保持され、すべての演算は分かりやすく関数的です。特別な構文 ``$|key|`` によって文字列のキーを表現することができます。 :: osh>table = $(Map) osh>table = $(table.add x, int) osh>table. += $|y| = int osh>table.find(y) - : "int" : Sequence * channel - チャネル * コンストラクタ: ``$(fopen , )`` 10.8.4 * オブジェクト: ``InChannel`` 12.1.16, ``OutChannnel`` 12.1.17 * チャネルオブジェクトは入力や出力のバッファとして使います。 * function - 関数 * コンストラクタ: ``$(fun , )`` 9.5.1 * オブジェクト: ``Fun`` 12.1.9 * 関数オブジェクトはいろんな方法で定義できます。 * 無名関数 :: $(fun i, j, $(add $i, $j)) * 名前をつけた関数 :: f(i, j) = add($i, $j) * *この機能はバージョン0.9.9.0で導入されました。* 無名関数の引数 :: osh>foreach(i => $(add $i, 1), 1 2 3) - : : Array * lexer - 字句解析 * オブジェクト: ``Lexer`` 10.11.9 * このオブジェクトは字句解析器として表現します。 * parser - パーサ * オブジェクト: ``Parser`` 10.11.13 * このオブジェクトはパーサとして表現します。