MikoScript3 言語仕様
箱の操作
本言語処理システムでは、箱の操作を行なう各種のリレー型関数が、予め組み込まれて
います。本章では、これらの関数について説明します。なお、箱の基本事項については、
「箱」の章で、説明しています。
基本操作
'exist? 箱の存在確認
'empty! 空箱化
'new! 空箱の新規生成/既存箱の空箱化
'name 箱名の取得/変更
'size 箱/値のサイズを取得
'type 箱/値のタイプを取得
'attr 箱/値の属性を取得/設定
'count 箱の中の箱の個数を取得
'level 箱の(入れ子の)深さを取得
'cbox! 「箱を入れる箱」を生成
'cbox? 「箱を入れる箱」か?
'same? 同一の箱か?
'ref 対象の箱への参照値 ⇒参照
'ref? 対象は参照箱または参照値か? ⇒参照
'alias 対象の箱を参照する箱を取得 ⇒参照
'val 実値への変換(参照の解消)
特定位置の箱の参照
'up 上位箱
'first 最初の箱
'last 最後の箱
'next 次の箱
'prev 前の箱
'after 後置箱
'before 前置箱
'fwd 先方箱
'bwd 前方箱
出し入れ
'queue! 双方向出し入れ用の箱を生成 ⇒参照
'push 対象箱内に指定項目を先頭から追加 ⇒参照
'post 対象箱内に指定項目を末尾から追加 ⇒参照
'pop 対象箱内の最初の箱を取り出す ⇒参照
箱内移動
'move 対象箱内の指定箱を現順位に移動する
'swap 対象箱と指定の箱の順序を入れ換える
'sort 対象箱内の箱を並べ替える(1)
'sort 対象箱内の箱を並べ替える(2)
'rotate 対象箱内の箱の順番を回転する
'reverse 対象箱内の箱の順番を逆にする
列挙
'each 対象箱内の直属の箱を列挙する(フラット走査)
'enum 対象箱内の直系の箱を列挙する(ツリー走査)
■基本操作
'exist? 関数
書式: <対象箱>'exist?
説明: <対象箱> の存在を確認します。
返値: <対象箱> が存在すれば 真値(1)、存在しなければ 偽値(0)
注意: 対象が値の場合、返値は、常に 真値(1) になります。
但し、対象が null の場合、返値は、偽値(0) になります。
用例: 次のスクリプトを実行すると、「1,0」とプリントされます。
A = 1;
print A'exist?, B'exist?;
'empty! 関数
書式: <対象箱>'empty!
説明: <対象箱> の箱の中身を空にします。
<対象箱> が存在しない時は、例外が発生します。
返値: <対象箱> への参照値 or null(対象が箱でない場合)
'new! 関数
書式: <対象箱>'new!
説明: <対象箱> が存在しない時は、その名前の空箱を新規に生成します。
<対象箱> が存在する時は、その箱を空にします。
返値: <対象箱> への参照値
'name 関数
書式: <対象箱>'name ・・・ 箱名の取得
<対象箱>'name( <箱名> ) ・・・ 箱名の変更
説明: <箱名> の引数が無ければ、<対象箱> の箱名を取得します。
<箱名> の引数が有れば、<対象箱> の箱名をそれに変更します。
なお、箱名の変更時、同じ箱名の箱が他にあれば、エラーになります。
返値: 取得/変更した箱名(正常時) or null(エラー時)
補説: 本関数の場合、エラーになっても例外は発生しません。
用例: 次のスクリプトは、「A, 春」と「春, B, <null>」をプリントします。
A = "春";
print A'name, [A]'new!'name;
A'name( "B" );
print B, B'name, C'name;
'size 関数
書式: <対象>'size
説明: <対象> は、箱か、または、値になります。
箱の場合は、その中身のデータサイズ(バイト数)を返します。
値の場合は、その値のデータサイズ(バイト数)を返します。
<対象> に「入出力形式」が設定されていれば、それに対応するサイズ、
つまり、実際に入出力されるサイズを返します。
なお、<対象> が不正な場合、-1 を返します。
用例: 次のスクリプトを実行すると、「4, 8, 12, 24」とプリントされます。
A = 12.3; B = "文字列データ";
C ::= { .Name'C(20); .Age'LONG; }
print 123'size, A'size, B'size, C'size;
'type 関数
書式: <対象>'type( i )
説明: 本関数は、<対象>(箱または値)のタイプを示す文字列を返します。
この主なものを下表に示します。
タイプ | 意味 |
null | 無効値 |
empty | 空箱 |
integer | 整数箱 or 値 |
float | 実数箱 or 値 |
string | 文字列箱 or 値 |
array | 純粋配列箱 |
container | 一般の「箱を入れる箱」 |
(クラス名) | クラス(構造体)箱 ※ |
class | クラス(構造体)箱 ※ |
instance | インスタンス箱 ※ |
usr-func | ユーザー定義関数箱 |
sys-func | システム組込関数箱 |
reference | 参照 |
bit-field | ビットフィールド箱 |
sys-data | システムデータ箱 |
dll-func | DLL関数箱 |
dll-data | DLLデータ箱 |
com-object | COMオブジェクト箱 |
※ が付いてるタイプについて、以下に説明します。
なお、引数 i が関連するのは、このタイプだけです。
<対象> がクラス(構造体)の場合:
i が省略または 0 の時、<対象> のクラス名(箱名)を返します。
i > 0 の時、第 i 番目の直接の基底クラスの箱名(クラス名)を返します。
多重継承がなければ、i = 1 です。なお、ここでは、間接の基底クラスは、
対象外です。i に対応するクラスがない時は、それを意味する "[?]" と
いう文字列を返します。
i < 0 の時、"class" というタイプ名を返します。これは、<対象> が
クラス(構造体)かどうかだけ分かればよい時に使います。
<対象> がインスタンスの場合:
i が省略または 0 の時、<対象> を生成したクラスの名前(箱名)を返します。
i < 0 の時、"instance" というタイプ名を返します。これは、<対象> が
インスタンスかどうかだけ分かればよい時に使います。
i > 0 の時、対応クラスが無いことを示す "[?]" という文字列を返します。
補説: 純粋配列の場合、さらにどのデータ型かを調べるには、'attr を使います。
クラス(構造体)箱、または、インスタンス箱の場合、その基底クラスの名前
ではなく、参照を得するには、'base を使います。
注意: 特殊な箱では、この表以外のタイプになる場合もあります。
<対象> が参照箱の場合、その参照先の箱のタイプを返します(「例3」参考)。
<対象> がない場合は、null を返します。
例1: 次のスクリプトは、「integer, float, string, array」とプリントします。
A = 12; B = 34.5; C = "xyz"; D'BYTE(100);
print A'type, B'type, C'type, D'type;
例2: 対象がクラス(構造体)とインスタンスの例を示します。
class A {}
class B {}
class C : A, B {}
V = C();
print A'type, B'type;
print C'type, C'type(1), C'type(2), C'type(-1);
print V'type, V'type(1), V'type(2), V'type(-1);
このスクリプトを実行すると、次のようにプリントされます。
A, B
C, A, B, class
C, [?], [?], instance
例3: 次のスクリプトは、「integer, reference」とプリントします。
A = 1;
R := A;
print R'type, A'ref'type;
'attr 関数
書式: <対象>'attr ・・・ 入出力形式または汎用属性値の取得
<対象>'attr( n ) ・・・ 汎用属性値の設定
説明: 本関数は、<対象>(箱または値)に設定されている属性値を取得/設定します。
ここでいう属性値とは、「入出力形式」または「汎用属性値」のことです。
<対象> に入出力形式が設定されている時に、この 'attr を引数なしで適用する
と、その形式を示す文字列(下表の「形式名」)を返します。また、数量を使用
する形式では、その数量(下表のnの値)も返します。
形式名 | 意味 |
C | n桁の ASCII 文字 |
I | 10進整数n桁の ASCII 文字列 |
X | 16進整数n桁の ASCII 文字列 |
F | 実数n桁の ASCII 文字列 |
LINE | 改行終端文字列 |
CSZ | 0終端文字列 |
T | n桁の任意文字列 |
BIT_FIELD | n バイトのビットフィールド |
SBIT | n ビット整数値(符号有り) |
UBIT | n ビット整数値(符号無し) |
BYTE | 8 ビット整数値(符号有り) |
UBYTE | 8 ビット整数値(符号無し) |
SHORT | 16ビット整数値(符号有り) |
USHORT | 16ビット整数値(符号無し) |
LONG | 32ビット整数値(符号有り) |
ULONG | 32ビット整数値(符号無し) |
FLOAT | 32ビット実数値 |
DOUBLE | 64ビット実数値 |
STRUCT | 構造体 |
FILE | ファイル/バッファ |
<対象> に入出力形式が設定されていない時に、この 'attr を引数なしで
適用すると、その <対象> の汎用属性値を返します。
'attr では、入出力形式の設定はできません。
'attr で設定はできるのは、汎用属性値だけです。
<対象> に、引数 n を指定して、この 'attr を適用すると、その n の値の
汎用属性値が、<対象> に設定されます。この値の有効範囲は現状、0〜1023 に
限定されています。これ以外の値を指定しても、0 に設定されます。
汎用属性値の設定の際に、入出力形式は解除されます。
汎用属性値は、入出力形式を解除できない純粋配列やファイル/バッファなど
には設定できません。
汎用属性値の用途は、特に規定されていません。何に使っても構いません。
補説: 属性値の取得の際、<対象> の属性が未設定、または <対象> が不正/不在なら、
0 を返します。また、汎用属性値の設定に成功した時は、<対象> の参照、または、
値を返し、失敗した時は、null を返します。
例1: 次の実行では、「0, LINE, LONG, STRUCT, 0」とプリントされます。
A = 0; B'LINE; C'LONG; D ::= { };
print A'attr, B'attr, C'attr, D'attr, X'attr;
例2: 次の実行では、「C, 8」とプリントされます。
Str'C(8);
print Str'attr;
例3: 次の実行では、「123」とプリントされます。
Tmp'new!'attr( 123 );
print Tmp'attr;
'count 関数
書式: <対象箱>'count ・・・ 「箱を入れる箱」内の箱数を取得
<純粋配列>'count( <次元> ) ・・・ 純粋配列の要素数を取得
<文字列>'count( s ) ・・・ サブ文字列の出現回数を取得
説明: 対象が「箱を入れる箱」の場合:
その箱の中にある直属の箱の個数を返します。
対象が純粋配列の場合:
<次元> の指定が無ければ、全要素数を返します。
<次元> の指定が有れば、その次元だけの要素数を返します。
なお、<次元> には、n 次元の配列の場合、1 〜 n の数値が指定できます。
対象が文字列の場合:
対象の文字列内に、引数 s の文字列が、何個あるかを返します。
対象が上記以外の場合:
-1 を返します。
用例: 次のスクリプトの実行では、「3, 200, 10, 20, 8」とプリントされます。
A ::= { .X = .Y = .Z = 0; }
B'SHORT( 10, 20 );
C = "すもももももももものうち";
print A'count, B'count, B'count(1), B'count(2), C'count("も");
'level 関数
書式: <対象箱>'level
説明: <対象箱> の入れ子の深さ、つまり、<対象箱> を含む最外の箱から、<対象箱>
までの、直属スコープの段数を返します。
なお、対象が不在または箱でない場合は、-1 を返します。
用例: 次のスクリプトの実行では、「1, 2, 3, -1」とプリントされます。
A.B.C = 0;
print A'level, A.B'level, A.B.C'level, X'level;
'cbox! 関数
書式: <対象箱>'cbox!
説明: <対象箱> が「箱を入れる箱」でなければ、強制的にそれを「箱を入れる箱」に
変えます。なお、その時点で、その箱の中には何の箱もありません。
<対象箱> が「箱を入れる箱」の場合は、そのままにしておきます。
<対象箱> が不在の時は、その箱を新規に生成します。
対象が値または無指定の場合は、エラーになります。
返値: <対象箱> への参照値 or null(エラー時)
用例: 次のスクリプトは、X という名前の「箱を入れる箱」をデフォールトスコープに
新規生成し、そのタイプ「container」をプリントします。
X'cbox!;
print X'type;
'cbox? 関数
書式: <対象>'cbox?
返値: <対象> が「箱を入れる箱」なら 真値(1)、さもなければ 偽値(0)
用例: 次のスクリプトを実行すると、「1,0」とプリントされます。
A'cbox!;
print A'cbox?, B'cbox?;
'same? 関数
書式: <対象>'same?( <箱名> )
返値: <対象> の箱が <箱名> の箱と同一の箱なら 真値(1)、さもなければ 偽値(0)
説明: 本関数は、箱の中身ではなく、その箱自身が同一か否かを判定します。
<対象> や <箱名> の箱が、参照箱の場合、その参照先の箱が判定されます。
用例: 次のスクリプトを実行すると、「1, 1, 1, 0」とプリントされます。
A = 123;
B := A;
C := B;
X = 123;
print A'same?( B ), B'same?( C ), C'same?( A ), A'same?( X );
'val 関数
書式: <対象>'val
説明: <対象> を実値に変換して(参照を解消して)返します。
<対象> が既に実値の時は、そのまま返します。
<対象> が実値に変換できない時は、null を返します。
補説: 'val は主に、関数の引数を「値渡し」にする時や、関数側で受け取った引数の
参照を解消する時に使います。⇒参照
■特定位置の箱の参照
'up 関数
書式: <対象箱>'up( i )
説明: <対象箱> よりも i 段上位の箱への参照を返します。
引数 i には、1, 2, ... を指定します。
i が省略時は、i = 1 として扱われます。
i = 0 の時は、<対象箱> 自身への参照を返します。
i に対応する箱が無い時や、対象が箱以外の時は、null を返します。
用例: 次のスクリプトを実行すると、「C, B, A」とプリントされます。
T := A.B.C'new!;
print T'name, T'up'name, T'up(2)'name;
'first 関数
書式: <対象箱>'first( i )
説明: <対象箱> 内の最初の箱から順方向に i 個先の箱への参照を返します。
引数 i には、0, 1, 2, ... を指定します。これは、次のように対応します。
i = 0: 最初の箱
i = 1: 最初の箱から1つ次の箱
i = 2: 最初の箱から2つ次の箱
・・・
i が省略時は、i = 0 として扱われます。
i に対応する箱が無い時や、対象が箱以外の時は、null を返します。
例1: 次の実行では、「1, A」と「3, C」と「A=1, B=2, C=3, 」がプリントされます。
T ::= { .A = 1; .B = 2; .C = 3; }
print T'first, T'first'name;
print T'first(2), T'first(2)'name;
for( p := T'first ; p'ref? ; p := T'next )
print p'name : "=" : p, -;
例2: 次の実行では、「11, 22, 33」と「11, <null>, 33」がプリントされます。
A = { 0, 0, 0 };
A'first = 11; A'first(1) = 22; A'first(2) = 33;
print A[0], A[1], A[2];
delete [ A'first(1)'ref ];
DefValue = null;
print A[0], A[1], A[2];
補説: 正常終了時、<対象箱> 内の「現指示箱」が、返値の箱に更新されます。
これは、'next と 'prev の基準になります。
'last 関数
書式: <対象箱>'last( i )
説明: <対象箱> 内の最後の箱から逆方向に i 個前の箱への参照を返します。
引数 i には、0, 1, 2, ... を指定します。これは、次のように対応します。
i = 0: 最後の箱
i = 1: 最後の箱から1つ前の箱
i = 2: 最後の箱から2つ前の箱
・・・
i が省略時は、i = 0 として扱われます。
i に対応する箱が無い時や、対象が箱以外の時は、null を返します。
例1: 次の実行では、「3, C」と「1, A」と「C=3, B=2, A=1, 」がプリントされます。
T ::= { .A = 1; .B = 2; .C = 3; }
print T'last, T'last'name;
print T'last(2), T'last(2)'name;
for( p := T'last ; p'ref? ; p := T'prev )
print p'name : "=" : p, -;
例2: 次の実行では、「11, 22, 33」と「11, <null>, 33」がプリントされます。
A = { 0, 0, 0 };
A'last = 33; A'last(1) = 22; A'last(2) = 11;
print A[0], A[1], A[2];
delete [ A'last(1)'ref ];
DefValue = null;
print A[0], A[1], A[2];
補説: 正常終了時、<対象箱> 内の「現指示箱」が、返値の箱に更新されます。
これは、'next と 'prev の基準になります。
'next 関数
書式: <対象箱>'next( i )
説明: <対象箱> 内の「現指示箱」から i 個先の箱への参照を返します。
現指示箱に関しては、'first と 'last の「補説」参照。
引数 i は、0, ±1, ±2, ... を指定します。これは次のように対応します。
i = 0: 現指示箱
i = 1: 現指示箱から1つ次の箱
i = 2: 現指示箱から2つ次の箱
・・・
i = -1: 現指示箱から1つ前の箱
i = -2: 現指示箱から2つ前の箱
・・・
i が省略時は、i = 1 として扱われます。
i に対応する箱が無い時や、対象が箱以外の時は、null を返します。
補説: 本関数の正常終了時、現指示箱は、返値の箱に更新されます。
用例: 次のスクリプトは、「A, 1」,「B, 2」,「C, 3」とプリントします。
T ::= { .A = 1; .B = 2; .C = 3; }
for( p := T'first ; p'ref? ; p := T'next )
print p'name, p;
'prev 関数
書式: <対象箱>'prev( i )
説明: <対象箱> 内の「現指示箱」から i 個前の箱への参照を返します。
現指示箱に関しては、'first と 'last の「補説」参照。
引数 i は、0, ±1, ±2, ... を指定します。これは次のように対応します。
i = 0: 現指示箱
i = 1: 現指示箱から1つ前の箱
i = 2: 現指示箱から2つ前の箱
・・・
i = -1: 現指示箱から1つ次の箱
i = -2: 現指示箱から2つ次の箱
・・・
i が省略時は、i = 1 として扱われます。
i に対応する箱が無い時や、対象が箱以外の時は、null を返します。
補説: 本関数の正常終了時、現指示箱は、返値の箱に更新されます。
用例: 次のスクリプトは、「C, 3」,「B, 2」,「A, 1」とプリントします。
T ::= { .A = 1; .B = 2; .C = 3; }
for( p := T'last ; p'ref? ; p := T'prev )
print p'name, p;
'after 関数
書式: <対象箱>'after( i )
説明: <対象箱> から i 個先の箱への参照を返します。
引数 i は、0, ±1, ±2, ... を指定します。これは次のように対応します。
i = 0: <対象箱> 自身
i = 1: <対象箱> から1つ次の箱
i = 2: <対象箱> から2つ次の箱
・・・
i = -1: <対象箱> から1つ前の箱
i = -2: <対象箱> から2つ前の箱
・・・
i が省略時は、i = 1 として扱われます。
i に対応する箱が無い時や、対象が箱以外の時は、null を返します。
用例: 次のスクリプトは、「A」,「B」,「C」,「<null>」とプリントします。
T ::= { .A = 1; .B = 2; .C = 3; }
for( i = 0 ; i <= 3 ; i++ )
print T.A'after(i)'name;
'before 関数
書式: <対象箱>'before( i )
説明: <対象箱> から i 個前の箱への参照を返します。
引数 i は、0, ±1, ±2, ... を指定します。これは次のように対応します。
i = 0: <対象箱> 自身
i = 1: <対象箱> から1つ前の箱
i = 2: <対象箱> から2つ前の箱
・・・
i = -1: <対象箱> から1つ次の箱
i = -2: <対象箱> から2つ次の箱
・・・
i が省略時は、i = 1 として扱われます。
i に対応する箱が無い時や、対象が箱以外の時は、null を返します。
用例: 次のスクリプトは、「C」,「B」,「A」,「<null>」とプリントします。
T ::= { .A = 1; .B = 2; .C = 3; }
for( i = 0 ; i <= 3 ; i++ )
print T.C'before(i)'name;
'fwd 関数
書式: <対象箱>'fwd( i )
説明: <対象箱> から i 個先方(下記補説参照)の箱への参照を返します。
引数 i は、0, ±1, ±2, ... を指定します。これは次のように対応します。
i = 0: <対象箱> 自身
i = 1: <対象箱> から1つ先方の箱
i = 2: <対象箱> から2つ先方の箱
・・・
i = -1: <対象箱> から1つ前方の箱
i = -2: <対象箱> から2つ前方の箱
・・・
i が省略時は、i = 1 として扱われます。
i に対応する箱が無い時や、対象が箱以外の時は、null を返します。
補説: ここでの「先方」「前方」の意味は、次のとおりです。
階層構造を深さ優先で展開して各ノードを1行に表わすと、例えば、次のように
なります。
R
├─A
│ ├─A1
│ └─A2
├─B
│ └─B1
└─C
あるノードから1つ先方のノードというのは、上図のような展開において、その
ノードから1行下のノードになります。また、あるノードから1つ前方のノード
というのは、そのノードから1行上のノードになります。たとえば、ノードBの
1つ先方のノードはB1で、1つ前方のノードはA2になります。
用例: 次のようなスクリプトがあります。
R ::= {
.A ::= { .A1 = 11; .A2 = 12; }
.B ::= { .B1 = 21; }
.C = 3;
}
for( p := R ; p'level > 0 ; p := p'fwd )
print p'name;
これを実行すると、次のようにプリントされます。
R
A
A1
A2
B
B1
C
'bwd 関数
書式: <対象箱>'bwd( i )
説明: <対象箱> から i 個前方の箱への参照を返します。
引数 i は、0, ±1, ±2, ... を指定します。これは次のように対応します。
i = 0: <対象箱> 自身
i = 1: <対象箱> から1つ前方の箱
i = 2: <対象箱> から2つ前方の箱
・・・
i = -1: <対象箱> から1つ先方の箱
i = -2: <対象箱> から2つ先方の箱
・・・
i が省略時は、i = 1 として扱われます。
i に対応する箱が無い時や、対象が箱以外の時は、null を返します。
なお、「先方」「前方」の意味は、'fwd の補説参照。
用例: 次のようなスクリプトがあります。
R ::= {
.A ::= { .A1 = 11; .A2 = 12; }
.B ::= { .B1 = 21; }
.C = 3;
}
for( p := R.C ; p'level >= 2 ; p := p'bwd )
print p'name;
これを実行すると、次のようにプリントされます。
C
B1
B
A2
A1
A
■箱内移動
'move 関数
書式: <対象箱>'move( A, "before", B )
<対象箱>'move( A, "after", B )
説明: "before"の時、<対象箱> 内の箱Aを箱Bの前へ移動します。
"after" の時、<対象箱> 内の箱Aを箱Bの後へ移動します。
注意: 箱Aは、省略不可
箱Bの省略時は、現指示箱( 'first 等の「補説」参照)になります。
"before","after" の省略/不正時は、"before" として扱います。
返値: <対象箱> への参照( エラー時は、null )
用例: 次のようなスクリプトがあります。
T ::= { .A = 1; .B = 2; .C = 3; }
T'move( T.A, "after", T.B );
do T'each with p { print p'name : "=" : p, -; };
print;
T'move( T.C, "before", T.B );
do T'each with p { print p'name : "=" : p, -; };
print;
これを実行すると、次のようにプリントされます。
B=2, A=1, C=3,
C=3, B=2, A=1,
'swap 関数
書式: 'swap( A, B )
A'swap( B )
説明: 箱Aと箱Bの順序を入れ換えます。
なお、両箱の上位の箱は、同じでないといけません。
返値: 箱A への参照( エラー時は、null )
用例: 次のスクリプトを実行すると、「C=3, B=2, A=1, 」とプリントされます。
T ::= { .A = 1; .B = 2; .C = 3; }
'swap( T.A, T.C );
do T'each with p { print p'name : "=" : p, -; };
print;
'sort 関数(1)
書式: <対象箱>'sort( <比較関数> )
説明: <対象箱> の中の各箱を <比較関数> で比較した結果の順に並べ替えます。
<比較関数> の引数には、比較する2つの箱への参照が渡されます。
<比較関数> の返値は、比較する2つの箱をA,Bとすると、
= 0: AとBが等しい
< 0: AはBよりも先の順になる
> 0: AはBよりも後の順になる
となる数値を返す必要があります。
返値: <対象箱> への参照( エラー時は、null )
補説: 箱の並べ替えは、特定の用途に限れば、'sort 関数(2)の方が高速です。
例1: 配列内の数値を昇順に並べ替える例を示します。ちなみに、次のスクリプトを
実行すると、「1, 2, 3, 4, 5, 」とプリントされます。
T = { 5, 2, 1, 3, 4 };
function Cmp( a, b ) { return a - b; }
T'sort( Cmp );
for( p := T'first ; p'ref? ; p := T'next )
print p, -;
ちなみに、匿名関数を使うと、上記の2〜3行は、次の1行で書けます。
比較関数が簡単な場合は、この方が便利です。
T'sort( function( a, b ) { return a - b; } );
例2: do-with 式を使うと、例1のスクリプトは、もっと簡単に書けます。
T = { 5, 2, 1, 3, 4 };
do T'sort with a, b { return a - b; };
do T'each with p { print p, -; };
例3: 配列内の各箱をその名前の昇順に並べ替える例を示します。ちなみに、次の
スクリプトを実行すると、「A, B, C, D, E, 」とプリントされます。
T ::= { .C = .A = .D = .E = .B = 0; };
do T'sort with a, b { return a'name - b'name; };
do T'each with p { print p'name, -; };
例4: 配列内の各箱の中の特定の変数(この例では X という変数)をキーとして、
その値の降順に並べ替える例を示します。このスクリプトを実行すると、
「C.X=3, B.X=2, A.X=1, 」とプリントされます。
T ::= { .A.X = 1; .B.X = 2; .C.X = 3; }
do T'sort with a, b { return b.X - a.X; };
do T'each with p { print p'name : ".X=" : p.X, -; };
'sort 関数(2)
書式: <対象箱>'sort( mode, key )
機能: <対象箱> の中の各箱を mode と key で指定された順に並べ替えます。
引数: mode には、並べ替え方を規定する以下の文字列を指定します。
"+n": <対象箱> の中の各箱の名前の昇順
"-n": 〃 名前の降順
"+v": 〃 値の昇順
"-v": 〃 値の降順
"+k": 〃 の中の「キー箱」の値の昇順
"-k": 〃 の中の「キー箱」の値の降順
これらの場合、文字列の比較の際には、英字の大小は区別されません。
英字の大小を区別して並べ替えるには、それぞれ、次の指定にします。
"+N", "-N", "+V", "-V", "+K", "-K"
文字列の並べ替えは、上記の場合、基本的に、ユニコード順ですが、
日本語の辞書順に並べ替えるには、それぞれ、次の指定にします。
"+nj", "-nj", "+vj", "-vj", "+kj", "-kj"
日本語の辞書順に関しては、'jcmp 参照。
mode が、"+k", "-k", "+K", "-K" "+kj", "-kj" の時、
引数の key で、その「キー箱」の名前を指定します。こうすれば、
<対象箱> の中の各箱の中の key で指定された名前の箱の値が
比較されます。
mode が省略/不正時、"+n" として扱われます。
返値: <対象箱> への参照 ( エラー時は、null )
補説: 値による並べ替えでの比較は、数値どうしか、文字列どうしに限られます。
それ以外の比較が必要な場合には、結果は保証されません。
補説: この 'sort 関数(2)の並べ替えは、比較関数が内部関数であるのと、
クイックソートを採用しているので、高速です。
ただ、比較関数を任意に指定できないので、用途は限られます。
一方、'sort 関数(1)は、汎用的ですが、'sort 関数(2)ほど速くは
ありません。
注意: <対象箱> は「箱を入れる箱」でないといけません。
キー箱は、参照箱であってはいけません。
例1: 次のスクリプトは、「キー箱」を使わない例です。
T ::= { .A = 1; .B = 2; .C = 3; }
T'sort( "-n" ); // 箱名の降順にソート
do T'each with p { print p'name : "=" : p, -; };
print;
T'sort( "+v" ); // 箱値の昇順にソート
do T'each with p { print p'name : "=" : p, -; };
print;
このスクリプトを実行すると、次のようにプリントされます。
C=3, B=2, A=1,
A=1, B=2, C=3,
例2: 次のスクリプトは、「キー箱」を使う例です。この実行でも、例1と同じ
プリント結果になります。
T ::= { .A.X = 1; .B.X = 2; .C.X = 3; }
T'sort( "-k", "X" ); // 各箱内の X という箱の値の降順にソート
do T'each with p { print p'name : "=" : p.X, -; };
print;
T'sort( "+k", "X" ); // 各箱内の X という箱の値の昇順にソート
do T'each with p { print p'name : "=" : p.X, -; };
print;
例3: 次のスクリプトは、日本語の辞書順にソートする例です。
T = { "フルーツ", "ふるさと", "ブルー" };
T'sort( "+vj" ); // 辞書順にソート
do T'each with p { print p, -; };
print;
T'sort( "-vj" ); // 辞書の逆順にソート
do T'each with p { print p, -; };
print;
このスクリプトを実行すると、次のようにプリントされます。
ブルー, フルーツ, ふるさと,
ふるさと, フルーツ, ブルー,
'rotate 関数
書式: <対象箱>'rotate( n )
説明: <対象箱> の中の各箱の順番を回転します。
引数 n は、その絶対値で回転回数を指定します。また、
n の正負で、回転方向を規定します:
n > 0 の時、順方向( 順番が上がる方へ移動、尚、先頭は末尾へ移動 )
n < 0 の時、逆方向( 順番が下がる方へ移動、尚、末尾は先頭へ移動 )
n が省略/不正時は、n = 1 として扱われます。
返値: <対象箱> への参照 ( エラー時は、null )
補説: 'rotate は、対象が、文字列、整数値の時も有効です。
用例: 次のスクリプトは、以下の各コメントに示すようにプリントします。
T ::= { .A = 1, .B = 2, .C = 3, .D = 4, .E = 5; };
call Print; // →「A, B, C, D, E, 」
T'rotate( 1 );
call Print; // →「B, C, D, E, A, 」
T'rotate( -2 );
call Print; // →「E, A, B, C, D, 」
return;
Print:
do T'each with p { print p'name, -; };
print;
back;
'reverse 関数
書式: <対象箱>'reverse
説明: <対象箱> の中の各箱の順番を逆にします。
返値: <対象箱> への参照 ( エラー時は、null )
補説: 'reverse は、対象が、文字列、整数値、メモリーブロックの時も有効です。
用例: 次のスクリプトを実行すると、「E, D, C, B, A, 」とプリントされます。
T ::= { .A = 1, .B = 2, .C = 3, .D = 4, .E = 5; };
T'reverse;
do T'each with p { print p'name, -; };
■列挙
'each 関数
書式: <対象箱>'each( <関数> )
説明: <対象箱> の中にある直属の各箱を、その格納順に1つずつ、列挙します。
この列挙というのは、指定された <関数> のコールになります。その際、
引数として、各箱への参照が渡されます。
なお、<関数> の返値が、-1 であれば、それ以降の列挙は中止されます。
返値: <関数> をコールした回数
( 列挙中止時は、それまでに <関数> をコールした回数を負にした値 )
注意: 本関数は、<対象箱> の追加スコープ内にある箱は、列挙しません。
例1: 次のスクリプトは、「12, 34, 56, 78, 90, 」とプリントします。
T = { 12, 34, 56, 78, 90 };
function Dump( v ) { print v, -; }
T'each( Dump );
例2: do-with 式を使うと、例1のスクリプトは、次のように書けます。
T = { 12, 34, 56, 78, 90 };
do T'each with v { print v, -; };
例3: 列挙を中断する例を示します。このスクリプトは、「12, 34, 56 」と
プリントします。
T = { 12, 34, 56, 78, 90 };
do T'each with v {
print v, -;
return v > 50 ? -1 : 0; };
'enum 関数
書式: <対象箱>'enum( <関数> )
説明: <対象箱> の中にある直系のすべての箱を、その格納順に1つずつ、列挙します。
その際、列挙した箱が「箱を入れる箱」の時は、その中の各箱に対しても、
(再帰的に)列挙します。
この列挙というのは、指定された <関数> のコールになります。その際、
引数として、各箱への参照が渡されます。
なお、<関数> の返値が、-1 であれば、それ以降の列挙は中止されます。
返値: <関数> をコールした回数
( 列挙中止時は、それまでに <関数> をコールした回数を負にした値 )
注意: 本関数は、<対象箱> の追加スコープ内にある箱は、列挙しません。
用例: 中が階層になっている箱内の全ての箱を列挙する例を示します。
このスクリプトを実行すると、「A, A1, A2, B, B1, C, 」とプリントされます。
T ::= {
.A ::= { .A1 = 11; .A2 = 12; }
.B ::= { .B1 = 21; }
.C = 3;
}
do T'enum with p { print p'name, -; };