|
Vino 言語仕様の予定 ver. 0.02 2002/11/20
◆ お断り
この「Vino言語仕様」は、やまざきが勝手な妄想を膨らませて、こんな言語があればいいのにと、自分勝手な理想を書き連ねているというレベルのモノです。決して決して決して、こんな言語が実在するわけでも、開発中なわけでも、将来有望なわけでもありませんので、その点をくれぐれもご注意ください。(万が一気に入られて、開発してくださるという話であれば、大歓迎ではありますが。^^;)
◆ 特徴
・一言で表現するなら「スマートな言語」。スマートとは可能な限りシンプルな構文で、かつ可読性が高いことをめざします。
・小規模から大規模なコードまでと、広範囲に適用可能とする。どちらか言えば大規模なコードを主なターゲットとする。
・安全性を優先するためタイプセーフ(型チェック)に加えて変数と定数をはっきりと区別する。
(変数名を間違えることで、無関係な変数を更新してしまうバグを減らすため。また、コンパイラの最適化にも有利であると思われるため。)
・利便性を優先するためコンテナクラスを標準でサポートする。
・安全性を優先するためインターフェースという概念を重視する。
(いわゆるオブジェクト指向言語ではありません。オブジェクト指向の継承という概念が生産性や安全性に反しているという判断から、継承という概念は採用しない。)
・安全性を優先するためポインタという概念は無い。
(便利であるのは認めるところなので、制限つきで採用するかもしれません。しかし、ポインタはバグを誘発しやすいので出来ることなら採用したくない。)
◆ 簡単な実行例
次の例では定数 a に 5 を、定数 b に 2 を代入し、その合計を定数 c に代入した後、結果を表示する。
変数と定数を区別して扱っているところがこの言語の最初の特徴。
| 例 |
a
: 5 ;
b : 2 ;
c : a + b ;
sys.put( "答は {c} です。\n" ) ; |
・実行すると「答は 7 です。」と表示する。
・文(statement)の末尾はセミコロン( ; )。
・a : 5 ; は「定数 a を宣言し、初期値は 5」という意味。
・sys.put() は「画面に"....." を表示せよ」という命令。
・{c} は「定数 c の内容を展開せよ」という意味。 |
変数と定数を区別して扱う理由は、コンパイラの最適化性能を上げる意味もあるが、安全性やコードのメンテナンス(可読性)を上げることが主な目的である。定数宣言であれば、その値は変化しないということがわかるのでメンテナンス時には主に変数を追いかければよいことになる。
| ●1章、型、宣言文、リテラル |
Introduction |
主な型は、int, string, real の3種類である。それぞれ、整数、文字列、実数である。Vinoの特徴としては STLでいう、コンテナクラスを最初からサポートしているところになる。
| ■ コメント文 (プリプロセッサ) |
Comments |
C/C++ でいう、/* */ や // です。Vino では見た目を重視して、-- にしました。
| 予約語 |
--
/- -/ |
Vinoにデクリメント演算子は無いです。
a += -1 ; を使ってください。 |
| コメント |
-- コメント C++ の // と同じ
/- 複数行コメント
C++ の /* */ と同じ
-/ |
|
| ■ ウォーニング文 (プリプロセッサ) |
Warning |
コンパイル時に、意図的にウォーニングを出す。
また、コメントや文字列以外の文中で、\t コードやASCIIコード以外(特に0x80 以降のSJISなど)のコード使用はウォーニングとなり、次の改行コード(\n)までコメントと同様に無視される。
| 予約語 |
...
/. ./ |
| ウォーニング |
foo( ... ) ; -- たとえば「書きかけ」という意味で使う。構文としては「...」は無視される。
/.
メッセージ
メッセージ
./ -- メッセージがウォーニングとして表示される。
漢字などのSJISやEUCコードも行末(\n)までウォーニングになる
|
変数や定数には、型という属性がある。C/C++やJavaと同じように、コンパイル時に型のチェックが行われる。
俗に言う「タイプセーフ」な言語である。
bool は enum の特殊なケース。enum は vector[string] の特殊なケースと等価と思っていただいて良いです。
| 予約語 |
int -- 整数型
string -- 文字列型
real -- 実数型
enum -- 列挙型
bool -- ブーリアン型
|
int -- int64
string -- std::string
real -- double
enum -- C/C++ とほぼ同じ
bool -- C/C++ とほぼ同じ |
◆ 定数の書き方
定数名、コロン':'、型名、初期値(リテラルまたは式)、セミコロン';' の順に記述する。初期値の型がリテラルと同じ場合は、型名を省略できる。初期値の省略はできない。
| 定数 |
a : int 100 ; -- 宣言文 int 型で初期値 100 の定数
a : 100 ; -- リテラルから型 int が推測できる場合は省略できる
a : ; -- NG コンパイルエラー。初期値無しは不可
b : a + 1 ; -- 他の定数や変数、式を初期値にすることもできる
a : { x:100 ; out:x*3 ; } ; -- スコープも初期値になる(後述参照)
a : func NoName{ x:100 ; out:x*3 ; } ; -- と同じ意味
-- この場合スコープは関数定義と解釈されが先に実行される。その結果 out の値が
a の初期値として取り込まれるので a は 300 になる
|
|
◆ 変数の書き方
変数名、ドル'$'、型名、初期値(リテラルまたは式)、セミコロン';'の順に記述する。定数と同じように、初期値の型をリテラルから変更する必要が無い場合は、型名を省略できる。初期値は省略できない。
| 変数 |
a $ int 100 ; -- 宣言文 int 型で初期値 100 の変数
a $ 100 ; -- リテラルから型 int が推測できる場合は省略できる
a $ ; -- NG コンパイルエラー。初期値無しは不可
|
|
| ■ 定数(宣言) |
ConstantDeclarations |
定数の宣言。
C/C++ の const 変数と同じような概念。参照はできるが更新はできない変数。変数よりバグの作りこみが少ないという意味で積極的に使いたい機能。
定数の宣言にはコロン( : )を書き、初期値(リテラルか他の変数/定数/関数)で必ず初期化します。よって初期値の無い定数はありません。初期値の無い定数を作ろうとするとコンパイルエラーになります。
定数には更新・代入(=)ができません。
| 予約語 |
:
|
|
| 定数 |
a : int 0 ; -- 整数
b : string 'str' ; -- 文字列
c : bool true ; -- ブーリアン
d : real 3.14 ; -- 実数
e : vector[] 1, 2, 3, ; -- 動的配列(コンテナ)
f : map[] 1..'one', 2..'two', ; -- 連想配列(コンテナ)
a : 0 ; -- 整数 a : int 0 ; と同じ
a += 1 ; -- NG コンパイルエラー(定数は更新不可)
a : 100 ; -- NG コンパイルエラー(同じ名前は作れない)
b : 'str' ; -- 文字列 b : string 'str' ; と同じ
b += 'ing' ; -- NG コンパイルエラー(定数は更新不可)
c : true ; -- ブーリアン c : bool true ; と同じ
c = false ; -- NG コンパイルエラー(定数は更新不可)
d : 3.14 ; -- 実数 d : real 3.14 ; と同じ
d *= 2.0 ; -- NG コンパイルエラー(定数は更新不可)
e : 1, 2, 3, ; -- 動的配列(コンテナ) e : vector[] 1, 2, 3, ; と同じ
e <<= 5 ; -- NG コンパイルエラー(定数は更新不可)
e[3] += 1 ; -- NG コンパイルエラー(定数は更新不可)
f : 1..'one', 2..'two', ; -- 連想配列(コンテナ) f : map[] 1..'one', 2..'two', ;
sys.put( f[2] ) ; -- two が表示される
f[0] = 'zero' ; -- NG コンパイルエラー(定数は更新不可)
f[1] = 'ONE' ; -- NG コンパイルエラー(定数は更新不可)
g : a ; -- a と同じ整数 g : int a ; と同じ、g : string a ; はエラー。
sys.put( g ) ; -- 0 が表示される
|
|
| ■ 変数(宣言) |
VariableDeclarations |
変数の宣言。
更新可能な変数の宣言には、ドル( $ )を変数の後ろに記述する。この変数はあとで値が変化すること、定数より利用範囲が広いことを意味する。自由度が高い分、若干ではあるが定数よりバグを含む可能性も高くなる。
変数には更新・代入(=)ができます。その他の機能は定数と同じです。
| 予約語 |
$
|
|
| 変数 |
a $ int 0 ; -- 整数
b $ string 'str' ; -- 文字列
c $ bool true ; -- ブーリアン
d $ real 3.14 ; -- 実数
e $ vector[] 1, 2, 3, ; -- 動的配列(コンテナ)
f $ map[] 1..'one', 2..'two', ; -- 連想配列(コンテナ)
a $ 0 ;
-- 整数
a += 1 ;
-- OK
sys.put( a ) ; -- 1 が表示される
sys.put( a.type_name() ) ; -- $int が表示される
b $ 'str' ;
-- 文字列
b += 'ing' ; -- OK
sys.put( b ) ;
-- string が表示される
sys.put( b.type_name() ) ; -- $string が表示される
c $ true ;
-- ブーリアン
c = false ; -- OK
sys.put( c ) ;
-- false が表示される
sys.put( "c:{c}" ) ; -- c:false が表示される
sys.put( c.type_nmae() ) ; -- $bool が表示される
d $ 3.14 ; -- 実数 d : real 3.14 ; と同じ
d *= 2.0 ; -- OK
sys.put( d ) ; --
6.28 が表示される
sys.put( d.type_nmae() ) ; -- $real が表示される
e $ 1, 2, 3, ;
-- 動的配列(コンテナ) e $ vector[int] 1, 2, 3, ; と同じ
e <<= 5 ;
-- OK
e[3] += 1 ;
-- NG 配列内の int は定数
sys.put( e[0] ) ;
-- 1 が表示される
sys.put( e[1].type_nmae() ) ; -- int が表示される
sys.put( e[3] ) -- 5 が表示される
sys.put( e.type_nmae() ) ; -- $vector[int] が表示される
sys.put( e.size() ) ; -- 4 が表示される
f $ 1..'one', 2..'two', ; -- 連想配列(コンテナ) f $ map[] 1..'one', 2..'two', ;
sys.put( f[2] ) ;
-- two が表示される
f <<= 0..'zero' ; -- OK
f[1] = 'ONE' ; -- NG コンパイルエラー(定数は更新不可)
sys.put( f[1] ) ; -- one が表示される
sys.put( f[2].type_nmae() ) ; -- string が表示される
sys.put( f.type_nmae() ) ; -- $map[int..string] が表示される
sys.put( f.size() ) ; -- 3 が表示される
g $ a ; -- a と同じ整数(aが定数だとエラー)
++ g ; -- OK
sys.put( g ) ; -- 2 が表示される
sys.put( a ) ; -- 1 が表示される
|
|
◆定数、変数間の代入の考え方。(リファレンスになる)
定数と変数との間での直接代入(=)はできない。
代入の前に一旦、.copy() を使い変数でも定数でもないリテラル状態のインスタンスを作成し、型を変換する。
| .copy() |
i1 : 1 ; -- 定数 int 1
i2 $ 0 ; -- 変数 int 0
i2 = i1.copy() ; -- 定数から変数への変換の場合は copy() が必要
i3 $ i1.copy() ; -- 定数から変数への変換の場合は copy() が必要
i4 : i1 ; -- リファレンス(同じモノを指す)
i5 : i2.copy() ; -- 変数から定数への変換の場合は copy() が必要
i6 $ i2 ; -- リファレンス(同じモノを指す)
sys.put( i1.type_name() ) ; -- int が表示される
sys.put( i2.type_name() ) ; -- $int が表示される
sys.put( i3.type_name() ) ; -- $int が表示される
sys.put( i4.type_name() ) ; -- int が表示される
sys.put( i5.type_name() ) ; -- int が表示される
sys.put( i6.type_name() ) ; -- $int が表示される
-- この↑ケースでは i1,i4 および i2,i6 は同じモノを指している。
|
|
主に定数や変数の初期値に指定する。式の中にも定数として記述できる。
このあたりはC++やJavaとほとんど同じです。
| 予約語 |
true -- bool の予約語
false -- bool の予約語
|
|
| int |
1234 -- 10進数
-1234 -- 10進数
0x1234 -- 16進数
0b1010 -- 2進数
123_456_789 -- 途中のアンダーラインもリテラルとして認識(無視)される
0xABCD_1234 -- 16進数
0b1010_1111 -- 2進数 |
|
| string |
'ABC012' -- エスケープなしの文字列
'a = {a}\n' -- エスケープなしなので、そのまま a = {a}\n と解釈される
"a = {a}\n" -- エスケープありの文字列
|
|
"abc'def'ghi" -- ダブルクォーテーションの中ではシングルクォーテーションを
'abc"def"ghi' -- シングルクォーテーションの中ではダブルクォーテーションを使用できる
|
| real |
3.14 -- π
123e-4 -- 0.0123
|
|
| enum |
NAME : enum AAA, BBB, CCC, ; -- AAA BBB CCC がリテラル
NAME : vector[string] 'AAA', 'BBB', 'CCC', ; -- 上記とほぼ同じ意味 vector[] については後述参照
sys.put( AAA ) ; -- AAA が表示される
sys.put( AAA.str() ) ; -- AAA が表示される(上記と同じ意味)
sys.put( AAA.type_name() ) ; -- enum:NAME が表示される
|
enum は int より
string に近い |
| bool |
true -- 真
false -- 偽
bool : enum true, false, ; -- ほぼ同じ意味
sys.put true ; -- true が表示される
sys.put true.str() ; -- true が表示される(上記と同じ意味)
sys.put true.type_name() ; -- bool が表示される
|
|
◆エスケープシーケンス(\) を含む文字列
ダブルクォーテーションで囲まれた文字列の中ではバックスラッシュ( \ )は特別な意味を持つ。
| string |
"\t" -- タブ文字(\x09)
"\n" -- 改行(\x0a)
"\r" -- リターン(\x0d)
"\x1b" -- 文字コード(16進数)
"\"" -- ダブルクォーテーション( " )自身を表わす。
"\t1234\n" -- エスケープありの文字列
|
|
◆文字列中の式の展開
ダブルクォーテーションで囲まれた文字列の中では中括弧( {, } )は特別な意味を持つ。
| string |
"a = {a}\n" -- エスケープありの文字列内の { } は値を展開する。
-- "a = " + a.str() + "\n" と同じ意味
"--{02X:a}--" -- フォーマット(02X)付き文字列展開。
--
a を16進2桁以上で展開する。a が 15 なら '--0F--' となる。
--
"--" + a.str( "02X" ) + "--" ; -- と同じ意味
"{++a}{++a}" -- 式も書ける。a $ 15 なら '1617'
--
(++a).str() + (++a).str() -- と同じ意味
|
|
◆長い文字列
文字が長くて一行に収まりきらないときは、C/C++のように分割して記述する。
| string |
long_str : 'long_long_long_long_long_long_long_'
'long_long_long_long_long_long_string'
;
---改行も含まれる場合、こんな特殊な書き方もOK。
long_str : '
long_long_long_long_long_long_long_
long_long_long_long_long_long_string
' ;
---以下の書き方と意味は同じ
long_str : "\nlong_long_long_long_long_long_long_\n"
"long_long_long_long_long_long_string\n"
;
|
|
◆デフォルトのメソッド
リテラルというか、基本型(int, string, rea,enum,booll)には最初から使えるメソッドがあるので、以下のような書き方ができる。
| メソッド |
.str() -- 内容を文字列に変換して返す
.type_name() -- 型名を文字列で返す
|
|
| int |
sys.put( 12.str() ) ; -- 12 が表示される -- sys.put( '12' ; と同じ
sys.put( 12.str( '02X' ) ) ; -- sys.put( '0C' ; と sys.put( "{02X:12}" ; と同じ
sys.put( 100.type_name() ) ; -- int が表示される
|
|
| string |
sys.put( 'AB'.str() ) ; -- 意味がない(エラーではないが無視される)
sys.put( 'AB'.str( '4' ) ) ; -- sys.put( 'AB ' ; 右詰め4文字で表示される
-- sys.put( "{4:'AB'}"と同じ
sys.put( 'abc'.type_name() ) ; -- string が表示される
|
|
| real |
sys.put( (3.14).str() ) ;
-- 3.14 が表示される -- sys.put( '3.14' ; と同じ
sys.put( (3.14).str( '2.3' ) ) ; -- sys.put( ' 3.140' ; と sys.put( "{2.3:3.14}" ; と同じ
sys.put( (3.14).type_name() ) ; -- real が表示される
|
|
| enum |
NAME : enum AAA, BBB, CCC, ; -- AAA BBB CCC がリテラル
sys.put( BBB.str() ) ; -- BBB が表示される -- sys.put( 'BBB' ; と同じ
sys.put( BBB.str( '4' ) ) ; -- sys.put( 'BBB ' ; と sys.put( "{4:BBB}" ; と同じ
sys.put( BBB.type_name() ) ; -- enum:NAME が表示される
|
|
| bool |
sys.put( true.str() ) ; -- true が表示される -- sys.put( 'true' ; と同じ
sys.put( true.str( '5' ) ) ; -- sys.put( 'true ' ; と sys.put( "{5:true}" ; と同じ
sys.put( true.type_name() ) ; -- bool が表示される
|
|
C/C++ の STL で実装されているコンテナクラスと同じような概念。
| 予約語 |
arg[] -- 引数(異なる型をコンテナする静的配列)
vector[] -- 動的配列(コンテナ)
map[] -- 連想配列(コンテナ)
list[] -- リスト(コンテナ)
set[] -- セット(コンテナ)
|
arg -- これは無いね
vector -- std::vector<>
map -- std::map<>
list -- std::list<>
set -- std::set<> |
◆ 固定コンテナの書き方-- 外見も中身も定数(変更不可)
変数名、コロン':'、コンテナ名'['型名']'、初期値(リテラルまたは式)','、セミコロン';'の順に記述する。初期値からコンテナ名と型名が推測できる場合はコンテナ名も型名も省略できる。
省略
なし |
--コンテナ名、型名を省略しない記述
a1_arg : arg[int,string,] 100, 'abc', ;
b1_tbl : vector[int] 1, 2, 3, 4, ;
c1_map : map[int..string] 1..'one', 2..'two', ;
d1_lst : list[int] 1, 2, 3, 4, ;
e1_set : set[int] 1, 2, 3, 4, ;
sys.put( a1_arg.type_name() ) ; -- arg[int,string,] が表示される
sys.put( b1_tbl.type_name() ) ; -- vector[int] が表示される
sys.put( c1_map.type_name() ) ; -- map[int..string] が表示される
sys.put( d1_lst.type_name() ) ; -- list[int] が表示される
sys.put( e1_set.type_name() ) ; -- srt[int] が表示される
|
|
省略
あり |
--コンテナ名、型名を省略した記述
a2_arg : 100, 'abc', ; -- 異なる型が複数要素の場合 arg[] と解釈する
b2_tbl : 1, 2, 3, 4, ;
-- 同じ型が複数要素の場合は vector[] と解釈する
c2_map : 1..'one', 2..'two', ; -- ペア演算子(..)がある場合は map[] と解釈する
d2_lst : list[] 1, 2, 3, 4, ; -- 同じ型が複数要素の場合は vector[] と解釈するので、
e2_set : set[] 1, 2, 3, 4, ; -- list[] や set[] は vector[] と区別するために記述する
sys.put( a2_arg.type_name() ) ; -- arg[int,string,] が表示される
sys.put( b2_tbl.type_name() ) ; -- vector[int] が表示される
sys.put( c2_map.type_name() ) ; -- map[int..string] が表示される
sys.put( d2_lst.type_name() ) ; -- list[int] が表示される
sys.put( e2_set.type_name() ) ; -- srt[int] が表示される
|
|
◆可変コンテナの書き方-- 外見も中身も変数(変更可)
変数名、'$'、コンテナ名'[''$'型名']'、初期値(リテラルまたは式)','、セミコロン';'の順に記述する。
| 可変コンテナ |
--コンテナ名、型名を省略しない記述
a3_arg $ arg[$int,$string,] 100, 'abc', ;
b3_tbl $ vector[$int] 1, 2, 3, 4, ;
c3_map $ map[$int..$string] 1..'one', 2..'two', ;
d3_lst $ list[$int] 1, 2, 3, 4, ;
e3_set $ set[$int] 1, 2, 3, 4, ;
sys.put( a3_arg.type_name() ) ; -- $arg[$int,$string,] が表示される
sys.put( b3_tbl.type_name() ) ; -- $vector[$int] が表示される
sys.put( c3_map.type_name() ) ; -- $map[$int..$string] が表示される
sys.put( d3_lst.type_name() ) ; -- $list[$int] が表示される
sys.put( e3_set.type_name() ) ; -- $srt[$int] が表示される
-- 型名を省略すると変数($int)ではなく定数(int)になるので、変数宣言の型名は省略はできない
|
|
コンテナクラスの初期値の表現。
| 予約語 |
default -- コンテナの予約語 |
|
| arg[] |
-- コンテナ名arg[]、型名、省略なし
arg[int,] 1,
-- 引数型
arg[int,int,int,] 1, 2, 3,
arg[int,string,real,] 1, '2', 3.0, -- 違う型でも同じコンテナに入る
arg[int,$string,$real,] 1, '2', 3.0, -- 定数変数の混在も可
arg[] -- 要素数ゼロも可
-- コンテナ名arg[]、型名、省略あり
arg[] 1,
-- 1, のみでは vector[int] と解釈される
arg[] 1, 2, 3, -- 1,2,3, のみでは vector[int]
と解釈される
1, '2', 3.0, -- 型が違う場合は arg[...]
と解釈される
arg[] $1, '2', $3.0, -- 定数変数混在でも型名の省略はできる
|
|
| vector[] |
vector[int] 1, 2, 3, 4,
-- intの配列
vector[vector[int]] 1, 2,, 3, 4,, -- 配列の配列 ,,を , , と離しては書けない
vector[int]
-- 配列、要素数ゼロ(型名は省略できない)
vector[int] 1,
-- 1 つでも、',' は必須
vector[int] default:0, -- 配列範囲外に要素をもたせる
|
|
| map[] |
map[int..string] 1..'one', 2..'two',
-- 連想配列(1対1要素)
map[int..string]
-- 連想配列、要素数ゼロ
map[int..string] 1..'one',
-- 1 つでも、',' は必須
map[int..string] 0..1..'0〜1', 3..4..5..'3〜5', -- 複数要素から1要素への収束する連想配列
map[int..string] default..'null', -- 連想できない値に要素をもたせる
|
|
◆デフォルトのメソッド
コンテナ型(arg[], vector[], map[], list[],set[])には最初から使えるメソッドがあるので、以下のような書き方ができる。
| メソッド |
.str() -- 内容を文字列に変換して返す
.type_name() -- 型名を文字列で返す
.size() -- コンテナに格納されている要素数をintで返す
.each({}) -- each は関数 func{} 引数にし、要素数分の関数呼び出しを行なう
.copy() -- 定数でも変数でもないリテラル状態のインスタンスを作る。
-- 定数から変数、変数から定数に型変換する場合にコピーを使う
|
|
| arg[] |
a : arg[int,$string,$real,] 1, '2', 3.0, ;
sys.put( a.str() ) ;
-- 1,$'2',$3.0, が表示される
sys.put( a.type_name() ) ; -- arg[int,$string,$real,] が表示される
sys.put( a.size() ) ; -- 3 が表示される
a.each( func { sys.put( in ; } ) ; -- すべての要素 123.0 が表示される
a2 $ a.copy() ;
sys.put( a2.type_name() ) ; -- $arg[int,$string,$real,] が表示される
-- 特殊な(リテラルをじかに書く)書き方
sys.put( (1, '2', 3.0,).str() ) ; -- 1,$'2',$3.0, が表示される
|
|
| vector[] |
v : vector[int] 1, 2, 3, ; -- v を vector[int] 宣言
sys.put( v.str() ) ;
-- 1,2,3, が表示される
sys.put( v.type_name() ) ; -- vector[int] が表示される
sys.put( v.size() ) ; -- 3 が表示される
v.each( func{ sys.put( in ) ; } ) ; -- すべての要素 123 が表示される
v2 $ v.copy() ;
sys.put( v2.type_name() ) ; -- $vector[int] が表示される
-- 特殊な(リテラルをじかに書く)書き方
sys.put( (1, 2, 3,).str() ) ; -- 1,2,3, が表示される
|
|
| map[] |
m : map[int..string] 1..'one', 2..'two', ; -- 連想配列(1対1要素)
sys.put( m.str() ) ;
-- 1..'one',2..'two', が表示される
sys.put( m.type_name() ) ; -- map[int..string] が表示される
sys.put( m.size() ) ; -- 2 が表示される
m.each( func{ sys.put( in ) ; } ) ; -- すべての要素 1..one2..two が表示される
m2 $ m.copy() ;
sys.put( m2.type_name() ) ; -- $map[int..string] が表示される
-- 特殊な(リテラルをじかに書く)書き方
sys.put( (1..'one', 2..'two',).str() ) ; -- 1..'one',2..'two', が表示される
|
|
| list[] |
lst : list[int] 1, 2, 3, ; -- v を list[int] 宣言
sys.put( lst.str() ) ;
-- 1,2,3, が表示される
sys.put( lst.type_name() ) ; -- list[int] が表示される
sys.put( lst.size() ) ; -- 3 が表示される
lst.each( func{ sys.put( in ) ; } ) ; -- すべての要素 123 が表示される
lst2 $ lst.copy() ;
sys.put( lst2.type_name() ) ; -- $list[int] が表示される
-- 特殊な(リテラルをじかに書く)書き方
sys.put( (list[int] 1, 2, 3,).str() ) ; -- 1,2,3, が表示される
|
|
| set[] |
s : set[int] 3, 1, 4, ; -- s を set[int] 宣言
sys.put( s.str() ) ;
-- 1,3,4, が表示される
sys.put( s.type_name() ) ; -- set[int] が表示される
sys.put( s.size() ) ; -- 3 が表示される
s.each( func{ sys.put( in ; ) } ) ; -- すべての要素 134 が表示される
s2 $ s.copy() ;
sys.put( s2.type_name() ) ; -- $set[int] が表示される
-- 特殊な(リテラルをじかに書く)書き方
sys.put( (set[int] 3, 1, 4,).str() ) ; -- 1,3,4, が表示される
|
|
◆arg[] の書き方
| arg[] |
a : arg[] 1, ; -- a を arg 宣言
sys.put( a[0] ) ; -- 1 が表示される
sys.put( a[0].type_name() ) ; -- int が表示される
b : arg[] 1, $'2', $3.0, ; -- 定数変数混在 OK
c : arg[int,$string,$real,] 1, '2', 3.0, ; -- 定数変数混在(上記と同じ意味)
sys.put( b.type_name() ) ; -- arg[int,$string,$real,] が表示される
sys.put( b[0] ) ; -- 1 が表示される
sys.put( b[0].type_name() ) ; -- int が表示される
sys.put( b[1] ) ; -- 2 が表示される
sys.put( b[1].type_name() ) ; -- $string が表示される
sys.put( b[2] ) ; -- 3.0 が表示される
sys.put( b[2].type_name() ) ; -- $real が表示される
b[0] = 10 ; -- NG コンパイルエラー(更新不可)
b[1] = '10' ; -- 更新OK
sys.put( b[1] ) ; -- 10 が表示される
|
|
◆vector[] の書き方
| vector[] |
a : 1, 2, 3, ; -- a を vector 宣言
b : vector[] 1, 2, 3, ; -- b を vector 宣言(上記と同じ意味)
sys.put( a.type_name() ) ; -- vector[int] が表示される
sys.put( a[2] ) ; -- 3 が表示される
sys.put( a[2].type_name() ) ; -- int が表示される
c : $1, 2, $3, ; -- 定数変数を混在は不可 arg[] 型と認識される
d : vector[$int] 1, 2, 3, ; -- d を vector 宣言(全て変数として宣言)
e : vector[] $1, 2, 3, ; -- e を vector 宣言(上記と同じ意味)
sys.put( d.type_name() ) ; -- vector[$int] が表示される
sys.put( d.size() ) ; -- 3 が表示される
c[2] = 30 ; -- 更新OK
sys.put( c[2] ) ; -- 30 が表示される
sys.put( c[999] ) ; -- 配列の範囲外の参照は実行時に例外発生!
f : 1, 2, 3, default:0, -- default で範囲外の値を指定
sys.put( f.size() ) ; -- 3 が表示される
sys.put( f[0] ) ; -- 1 が表示される
sys.put( f[999] ) ; -- 0 が表示される
|
|
◆コンテナ間の代入の考え方。(リファレンスになる)
可変コンテナと固定コンテナとの間での直接代入(=)はできない。
代入の前に一旦、.copy() を使い定数でも変数でもないリテラル状態のインスタンスを作成する。
問題は、配列の中の型を変えるにはどうするか…(STLのようにtranslateアルゴリズムを用意するのか…)
| .copy() |
tbl1 : 1, 2, 3, 4, ; -- 固定コンテナ vector[int]
tbl2 $ [] ; -- [] は空の固定コンテナ(size:0)
tbl2 = tbl1.copy() ; -- 固定から可変への変換の場合は copy() が必要
tbl3 $ tbl1.copy() ; -- 固定から可変への変換の場合は copy() が必要
tbl4 : tbl1 ; -- リファレンス(同じモノを指している)
tbl5 : tbl2.copy() ; -- 可変から固定への変換の場合は copy() が必要
tbl6 $ tbl2 ; -- リファレンス(同じモノを指している)
sys.put( tbl1.type_name() ) ; -- vector[int] が表示される
sys.put( tbl2.type_name() ) ; -- $vector[int] が表示される
sys.put( tbl3.type_name() ) ; -- $vector[int] が表示される
sys.put( tbl4.type_name() ) ; -- vector[int] が表示される
sys.put( tbl5.type_name() ) ; -- vector[int] が表示される
sys.put( tbl6.type_name() ) ; -- $vector[int] が表示される
-- この↑ケースでは tbl1,tbl4 および tbl2,tbl6 は同じモノを指している。
|
|
◆すべての配列要素について処理を行うには.each() を使う。
.each() は関数を引数にするデフォルトのメソッド。
| .each() |
tbl : 'aa', 'bb', 'cc', ; -- 配列tblを 'aa', 'bb', 'cc' で初期化
tbl.each{ sys.put( in ) ; } ; -- すべての要素 aabbcc が表示される
tbl.each( -- aa
func { -- bb
sys.put( "{in}\n"
) ; -- cc
}
) ; -- 改行しながら表示される
|
|
◆map[] の書き方
| map[] |
a : 1..'one', 2..'two', ; -- 連想配列(1対1要素)
sys.put( a.type_name() ) ; -- map[int..string] が表示される
sys.put( a.size() ) ; -- 2 が表示される
sys.put( a[1].type_name() ) ; -- string が表示される
sys.put( a[1] ) ; -- one が表示される
sys.put( a[999] ) ; -- 配列の範囲外の参照は実行時に例外発生!
b : 'one'..1, 'two'..1, ; -- 連想配列
sys.put( b.type_name() ) ; -- map[string..int] が表示される
sys.put( b.size() ) ;
-- 2 が表示される
sys.put( b['one'].type_name() ) ; -- int が表示される
sys.put( b['one'] ) ; -- 1 が表示される
sys.put( b['zero'] ) ; -- 配列の範囲外の参照は実行時に例外発生!
c : [int..string] ; -- 連想配列、要素数ゼロ
sys.put( c.size() ) ; -- 0 が表示される
d : 0..1..'0〜1', 3..4..5..'3〜5', ; -- 複数要素から1要素への収束する連想配列
sys.put( d.size() ) ;
-- 5 が表示される
sys.put( d[5] ) ;
-- 3〜5 が表示される
e : 1..'one', default..'null', ; -- default で範囲外の値を指定
sys.put( e[1] ) ;
-- one が表示される
sys.put( e[999] ) ;
-- null が表示される
|
|
◆ペア演算子'..'を使った要素を配列とすると連想配列(map)になる。
ペア
演算子 |
mp $ 'one'..1, 'two'..2, ; -- string,intのペアを連想配列を宣言
mp $ map[string..int] 'one'..1, 'two'..2, ; -- 上の書き方と同じ意味
mp.push( 'zoro'..0 ) ; -- 追加だが、後ろに追加されるわけではない。
--(アルファベット順にソートされている)
mp <<= 'zero'..0 ; -- 上の書き方と同じ意味
sys.put( mp['one'] ) ; -- 'one'から連想される要素 1 が表示される
sys.put( mp.at( 'one' ) ) ; -- 上の書き方と同じ意味
|
|
◆すべての連想配列要素について処理を行う(each{})
| .each() |
mp.each( func { sys.put( in ) ; } ) ; -- すべての要素 one..1two..2zero..0 が表示される
mp.each( -- one..1
func { -- two..2
sys.put( "{in}\n"
) ; -- zero..0
}
) ; -- と改行しながら表示される
mp.each( -- one
func { -- two
sys.put( "{in.m_first}\n"
) ; -- zero
}
) ; -- と改行しながら表示される
|
|
◆コンテナの中も定数と変数を区別する(省略時は定数を優先)
コンテナ自体にも、可変と固定(コンテナの容量を増やして追加したり減らしたりできるのが可変コンテは。できないのが固定コンテナ)があります。さらに、コンテナの中身についても、変数を格納したコンテナと、定数を格納したコンテナがあります。
組み合わせは4パターンになってしまいます。このあたりもう少しすっきりとした仕様にしたいとは思うのですが、なかなかよいアイデアがありません。
| コンテナ内の定数と変数 |
i $ vector[$int] 1, 2, 3, ; -- 動的配列(コンテナ)
j $ map[$int..$string] 1..'one', 2..'two', ; -- 連想配列(コンテナ)
k $ vector[] $1, 2, 3, ; -- 動的配列(コンテナ)
l $ map[] $1..$'one', 2..'two', ; -- 連想配列(コンテナ)
m : $1, 2, 3, ; -- 動的配列(コンテナ)vector[$int]
m <<= 5 ; -- NG(追加はできない)
m[1] += -1 ; -- OK(2番目の要素を1引く)
m.each( func { sys.put( in ) ; } ) ; -- 113 が表示される
n : $1..$'one', 2..'two', ; -- 連想配列(コンテナ)map[$int..$string]
sys.put( n[2] ) ; -- two が表示される
n <<= 0..'zero' ; -- NG map[]は固定長
n <<= 1..'ONE' ;
-- OK
n[2] = 'TWO' ; -- OK
n.each( func { sys.put( in ) ; } ) ; -- 1..ONE2..TWO が表示される
|
|
2章につづきます。
|