Vino言語 (2/4) - やまざき@BinaryTechnology
「デスマーチと戦う武蔵流プログラマ やまざき のページ」

TopPage
(サイトマップ)


Book
(書籍)


「火事場プロジェクトの法則」
サポートページ


「LHAとZIP」
サポートページ



Document
(文章)

デスマーチの記録に見る
運命の分かれ道
NEW!

武蔵流プログラマからの提言

武蔵流プログラマが斬る Eclipse

コードデザイン最前線
1
2 3 4 5 6 7 8 9
10 11 12 13 ML

C++で読む
デザインパターン


ポインタ不要論

データ圧縮の基礎

プログラマへの
アドバイス


データ指向の話1 2

インターフェースの話


Diary & Books
(日記と本屋)

やまざきの
はてなダイアリ
(日記)
[] [PC] [資産運用]
[デスマ] [映画] [2足ロボ]

やまざきの本屋


SoftWorks
(ソフトウェア)


(1) DeepFreezer
(ディープ・フリーザー)
高速アーカイバ

(English Page)

(2) Closedown-Planet
(クローズダウン・プラネット)
アクションパズルゲーム


(3) PieceMaker
(ピース・メーカー)
ファイル分割/結合


(4) WakuPita
(枠ピタ)
ウィンドウ移動便利ツール

(English Page)

(5) ググ郎
(Bookmarklet)
選択文字列をGoogleで検索

NEW!


Developing
(開発中)


(1) DeepFreezer2
yz2dlg.dll alpha6


C Magazine特集yz2


Hobby & Favorite
(道楽/お気に入り)


2LegRobo
MindStorms



p.s.
(雑談)


Profile

i_want^^;


やまざきが書いた本


[システム開発]
火事場プロジェクトの法則
どうすればデスマーチをなくせるか?
2006/09/13 発売


LHAとZIP
圧縮アルゴリズム×プログラミング入門

奥村さんと共著です。
2003/12/01 発売


やまざきが寄稿した本


SEの読書術
「本質を読む」力を磨く10の哲学 2006/02発売。



開発の現場 Vol.002
「反デスマーチ大研究」という記事。2005/09/13発売。



Software People Vol.3
「武蔵流プログラマからの提言」という記事。2003/10/31発売。



Eclipse パーフェクトマニュアル vol.1
「武蔵流プログラマが斬る Eclipse」という記事。2003/06/05発売。




Vino言語(1/4) (2/4) (3/4) (4/4)


Vino 言語仕様の予定 ver. 0.02 2002/11/21

2章 構文関係(式、演算子、制御構文、関数) Statements

基本的に、式や演算子に関しては C/C++ や Java を継承しているつもり。
制御構文はバッサリと削った。関数の仕様については独自の路線に変えた。このあたり、最初に目にする人には違和感が多いかも。

Expression

基本的に C/C++ や Java の式と同じ。';' は式に含まれない。

a += 10   -- これは式
c = a + b -- これも式
foo()     -- 関数呼び出しも式
true      -- リテラルも式
{}        -- スコープも式(関数定義&呼び出しと同じ意味)


算術演算子 Arithmetic Operators

基本的に C/C++ や Java と同じ。
すべての演算子にはあらかじめメソッド名が割り当てられている。よって、すべての演算子はメソッド名の「シンタックスシュガー」であると言える。

予約語 ◆単項演算子(Unary Operator) シンタックスシュガー
++
-
x.add( 1 )
x.minus()
◆2項演算子(Binary Operator)
* / % + - << >> & | ^

& -- bit_and
| -- bit_or
^ -- bit_xor

x.copy().mul( y ) x.copy().div( y ) x.copy().mod( y )
x.copy().add( y ), x.copy().add( y.minus() )
x.copy().shift( y ), x.copy().shift( y.minus() )
x.copy().bit_and( y )
x.copy().bit_or( y ), x.copy().bit_xor( y )


論理演算子 Logical Operators

基本的に C/C++ や Java と同じ。

予約語 ◆単項演算子(Unary Operator) シンタックスシュガー
! x.not()
◆2項演算子(Binary Operator)
> < >= <= == != && || ^^

-- bool not
&& -- bool and
|| -- bool or
^^ -- bool xor
x.is_big( y ), x.is_small( y ).not(),
x.is_small( y ), x.is_big( y ).not(),
x.is_eq( y ), x.is_eq( y ).not()
x.and( y )
x.or( y ), x.xor( y )
論理演算子 a : 0 ;              -- int 型の定数
sys.put( a == 1 ) ;     -- 型のチェックもされる(OK)false
sys.put( a < 1 ) ;      -- true
sys.put( a == true ) ;  -- NG コンパイルエラー(型が違う)
sys.put( a == 'str' ) ; -- NG コンパイルエラー(型が違う)


代入演算子 Assignment Operators

基本的に C/C++ や Java と同じ。ただし、左辺が変数でないとコンパイルエラーになる。

シンタックスシュガー x += y を x.set( x + y ) 、 x + y は a.add(y) にするか、それとも x + y を x.copy()+=y 、x += y を x.add(y) にすべきか悩んでます。現状は後者を選択中。

予約語 =
*= /= %=
+= -= <<= >>= &= |= ^=
x.set( y )
x.mul( y ) x.div( y ) x.mod( y )
x.add( y ), x.add( y.minus() )
x.shift( y ), x.shift( y.minus() ), x.bit_and( y ))
x.bit_or( y ), x.bit_xor( y )
代入演算子 a $ 0 ;     -- int 型の変数

a = 1 ;     -- 型のチェックもされる(OK)
a = true ;  -- NG コンパイルエラー(型が違う)
a = 'str' ; -- NG コンパイルエラー(型が違う)

◆ 文字列連結

文字列連結 y : 'yyy' ;
z : 'zzz' ;
x $ y + z ; -- 文字列 y と 文字列 z を連結し、変数 x として宣言
x += y ;    -- x = x + y ; と同じ意味
sys.put( x ) ; -- yyyzzzyyy が表示される


演算子の優先順位

基本的に C/C++ や Java の式と同じ。
デクリメント演算子(--)はありません。

優先順位 予約語 シンタックスシュガー(予約メソッド)
高い x[y] 参照 x.at( y )
++x 更新 x.add( 1 )
!x -x(単項)
x*y x/y x%y
x+y x-y
x<<y x>>y
x&y
x|y x^y
x>y x>=y
x<y x<=y
x==y x!=y
x&&y
x||y x^^y
参照 x.copy().not(), x.copy().minus()
x.copy().mul( y ), x.copy().div( y ), x.copy().mod( y )
x.copy().add( y ), x.copy().add( y.copy().minus() )
x.copy().shift( y ), x.copy().shift( y.copy().minus() )
x.copy().bit_and( y )
x.copy().bit_or( y ), x.copy().bit_xor( y )
x.is_big( y ), x.is_small( y ).not()
x.is_small( y ), x.is_big( y ).not()
x.is_eq( y ), x.is_eq( y ).not()
x.copy().and( y )
x.copy().or( y ), x.copy().xor( y )
x=y
x*=y x/=y x%=y
x+=y x-=y
x<<=y x>>=y
x&=y
x|=y x^=y
更新 x.set( y )
x.mul( y ), x.div( y ), x.mod( y )
x.add( y ), x.add( y.copy().minus() )
x.shift( y ), x.shift( y.copy().minus() )
x.bit_and( y )
x.bit_or( y ), x.bit_xor( y )
低い x?y??z 参照 x.then( { y }, { z } )
「高い」「低い」は演算子の優先順位。
例えば「&&」は「||」より優先順位が高いので、以下のように解釈される。
a && b || c -- ( a && b ) || c と同じ意味
a || b && c -- a || ( b && c ) と同じ意味


Statements

基本的に C/C++ や Java と同じ。';' で区切られた式が文。

++ a ;                    -- これは文(1つ)
++ a ; b += 'ing' ;       -- これは複数の文
{ ++ a ; b += 'ing' ; } ; -- これは複数の文をまとめた1つの文


スコープ Scope

基本的に C/C++ や Java と同じ。ブロックともいう。
Vinoの中では、名前のないlabel と同じ意味。その場で宣言して、その場で実行しちゃう関数のようなもの。

予約語 { } out
スコープ a $ 100 ;
b : 1 ;
{               -- スコープの始まり
    a $ 200 ;   -- 同じ名前でも宣言できる
    c : 2 ;
    a += b ;    -- スコープの外 b は参照できる
    a += c ;
    sys.put( a ) ; -- 203 が表示される
} ;             -- スコープの終わり
a += b ;        -- a は101
sys.put( a ) ;     -- 101 が表示される
a += c ;        -- コンパイルエラー(c は参照できない)

out 宣言子(C++やJavaのpublicの概念)を使うことで、スコープ自体も値を持つことができる。
より具体的には、関数の宣言と、実行と、破棄を一行で行なっている。

out 宣言子 a : 10 ;
b : { out : 20 ; } ;                    -- b : 20 ; と同じ
c : { out  m_rtn : 30 ; } ;              -- c : 30 ; と同じ
d : { out  m_rtn : 40 ; m_rtn *= 2 ; } ; -- d : 80 ; と同じ

◆ スコープと関数宣言の区別と動作の違い

スコープとラベルはその場で実行される。それ以外の {} は関数宣言として解釈される。
ただし、関数宣言でも、変数や定数として値を要求される場合はその場で実行される。

{ } ... ;           { ... ; } ; -- スコープ、その場で実行
... ; label ... { ... ; } ; -- ラベル、その場で実行
... ; ...       { ... ; } ; -- 関数宣言のみとして扱う
... ; ... : ... { ... ; } ; -- 関数宣言し、その場で実行、結果を定数にする
... ; ... $ ... { ... ; } ; -- 関数宣言し、その場で実行、結果を変数にする


条件文 Selection Statements

C/C++ でいう if 文。3項演算子 ? : に使い方は似ているが、値を持たないので3項演算子ではない。
bool式 '?' 式1 2項演算子ではない(値は返さない)
bool式 '?' 式1 '??' 式2 3項演算子ではない(値は返さない)

予約語 ? ??
x.then({ y },{ z });
条件文 a > max ? a = max ; -- 代入 = より条件 ? のほうが優先度が低い
a > b ? a = b ?? b = a ;
a > b ? { a = b ; } ?? { b = a ; } ; -- スコープも書ける

-- 複数行もスコープで書ける
a > b ? {
    a = b ;
}
?? {
    b = a ;
} ;


制御構文 Jump Statements

繰り返し構文。C/C++ の label, goto に似ているが、スコープ(有効範囲)の概念があるのですこし違う。
基本的に break と continue のみなので、if, while, for などの制御構文がどうしてもほしい人は func か class で作ってください。というか、標準ライブラリで用意するつもりです。
最終的には、すべてがライブラリの呼び出しだけで記述できてしまって、 言語の基本部分(予約語 ?,??,label,break,continueとか)はライブラリの中にしか存在しないような形が理想かも。

予約語 label break continue end
continue label A          -- 無限ループ
{
    ...
    continue A ; -- label A の { まで戻る
}
end label A ;    -- end はコメントのようなもの(省略できる)

label A
{
    ...
} ;              -- end はコメントのようなもの(省略できる)
continue A ;     -- NG コンパイルエラー(A のスコープの外だから)

label A              -- 無限ループ(外側)
{
    label A          -- 無限ループ(内側)同じ名前でもOK
    {
        ...
        continue A ; -- 内側の label A まで戻る
    } ;
    ...
    continue A ;     -- 外側の label A まで戻る
} ;

label           -- 無限ループ(ラベル名省略)
{
    ...
    continue-- 一番内側のlabel の { まで戻る
} ;

break label A         -- 無限ループ
{
    break A ;   -- label A の } までジャンプ
    ...         -- この文は実行されない
} ;

label A           -- 無限ループ(外側)
{
    label A       -- 無限ループ(内側)同じ名前でもOK
    {
        break A ; -- label A の } までジャンプ
        ...       -- この文は実行されない
    } ;
    break A ;     -- label A の } までジャンプ
    ...           -- この文は実行されない
} ;


◆ 0〜9 までを簡単に表示するには

繰り返し i $ 0 ;
label LOOP
{
    sys.put( i ) ;              -- 0〜9 表示
    ++ i ;
    i < 10 ? continue LOOP ; -- 繰り返し この場合、continue のみでも動作は同じ
} ;


◆ if-else文 if(...){...}else{...}構文はありません。?, ?? を用いて実装します。

if文 x > 5
? {
    sys.put( "5より大きい\n" ) ;
}
?? {
    sys.put( "5か、5より小さい\n" ) ;
} ;

-- 1行で書くと…
x > 5 ? sys.put( "5より大きい\n" ) ?? sys.put( "5か、5より小さい\n" ) ;

◆ while文 while(...){...}構文はありません。break, continue を用いて実装します。

while文 xx $ 1 ;
label WHILE
{
    10 <= in ? break WHILE ; -- 抜ける
    sys.put( "xx = {xx}\n" ) ;
    ++ xx ;
    continue WHILE ; -- 繰り返し この場合、continue のみでも動作は同じ
} ;
sys.put( "xx = {xx}\n" ) ;

◆ do-while文 do{...}while{...}構文はありません。continue を用いて実装します。

do-while文 x $ 0 ;
label DO
{
    sys.put( "x = {x}\n" ) ;
    ++ x ;
    in < 5 ? continue DO ; -- 繰り返し この場合、continue のみでも動作は同じ
} ;
sys.put( "x = {x}\n" ) ;

◆ switch-case文 switch{case:...}構文はありません。map[int..func] を用いて実装します。

switch文 switch_map : map[int..func{}]
    0..{ sys.put( 'zero' ) ; },
    1..{ sys.put( 'one' ) ; },
    2..{ sys.put( 'two' ) ; },
;

switch_map[0]() ;  -- zero が表示される
switch_map[1] ;    -- one が表示される。()を省略しても関数呼び出しと解釈される。
sys.put( switch_map[2].type_name() ) ; -- func{} が表示される


関数 Function

関数の書き方は C/C++ やJavaとは大きく異なる。
C++やJavaのclassと同じように関数と関数のインスタンスを区別する。

予約語 func
func foo : func Foo   -- 関数名が Foo で、関数の実行結果 foo の定義文
{
    ...
}
end func Foo ;   -- end はコメントのようなもの(省略できる)

foo : func       -- 名無し関数実行結果 foo の定義文(関数名は省略できる)
{
    ...
} ;              -- end はコメントのようなもの(省略できる)

func Foo         -- 関数名 Foo の定義文(この時点で関数は実行されない)
{
    ...
} ;              -- end はコメントのようなもの(省略できる)

func             -- 関数名も省略できる(この時点では実行されない)
{
    ...
} ;              -- end はコメントのようなもの(省略できる)

関数コール FunctionCalls

C/C++ でいう main 関数は無い。記述されている先頭から順に実行される。

予約語 ( )
関数呼び出し func Boo -- 関数名 Boo を宣言
{
    sys.put( "hello\n" ) ;
} ;
Boo() ; -- 関数コール hello を表示。引数なし、戻り値なし
Boo ;   -- 関数コール hello を表示。() は省略できる

func Foo -- 関数名省略(直接インスタンスを生成)
{
    out m_a : in[0] * in[1] ;
} ;
a : Foo( 10, 20 ) ; -- 引数2つ、戻り値1つ(定数)
b $ Foo( 10, 20 ) ; -- NG 変数 $arg[] は存在しない

sys.put( a.m_a ) ; -- 200 を表示
sys.put( a[0] ) ;  -- 200 を表示 -- sys.put( a.m_a ) ;と同じ
sys.put( a ) ;     -- 200 を表示 -- 戻り値が1つの場合は省略できる sys.put( a.m_a ) ;と同じ
sys.put( a.type_name() ) ;     -- arg[m_a:int,] を表示
sys.put( a.m_a.type_name() ) ; -- int を表示
sys.put( a[0].type_name() ) ;  -- int を表示

func Woo -- 関数名省略(直接インスタンスを生成)
{
    out m_a : in[0] * 10 ;
    out m_b : in[1] * 20 ;
} ;
c : Woo( 1.0, 2 ) ;  -- 引数2つ、戻り値2つ
sys.put( c.m_a ) ; -- 1つめの戻り値 10.0 を表示
sys.put( c.m_b ) ; -- 2つめの戻り値 40 を表示
sys.put( c[0] ) ;  -- 1つめの戻り値 10.0 を表示
sys.put( c[1] ) ;  -- 2つめの戻り値 40 を表示

sys.put( c ) ;     -- NG 戻り値が2つ以上の場合は省略不可
sys.put( c.type_name() ) ;     -- arg[m_a:real,m_b:int,] を表示
sys.put( c.m_a.type_name() ) ; -- real を表示
sys.put( c[0].type_name() ) ;  -- real を表示

◆ 関数を宣言

関数に渡された引数は argコンテナ in に格納されるので、in[0], in[1], in[2],...として参照することができる。in[0]など引数の型は関数コール時(コンパイル時)に決定する。
out は 関数の戻り値とすることを意味する。というか、クラスのインスタンスと同じ意味なんだけど。
このあたりから急にややこしくなっているかも…。もう少し説明が必要かな。

引数の型
未指定
-- 引数の型を決めずに受け取る
func
Add
{
    out : in[0] + in[1] ;

    -- sys.put( in.type_name() ) ; -- arg[int,int,] または arg[real,real,] または arg[string,string,] を表示する。引数の内容による。
    -- sys.put( in[0].type_name() ) ; -- int または real または string を表示する。引数の内容による。
} ;

-- 関数は宣言しただけでは実行されず、呼び出す事で実行される。

sys.put( Add( 3, 5 ) ) ;           -- 8 を表示
sys.put( Add( 3, 5 ).type_name() ) ; -- int を表示
sys.put( Add( 1.2, 3.4 ) ) ;           -- 4.6 を表示
sys.put( Add( 1.2, 3.4 ).type_name() ) ; -- real を表示
sys.put( Add( 'abc', 'def' ) ) ;           -- abcdef を表示
sys.put( Add( 'abc', 'def' ).type_name() ) ; -- string を表示
sys.put( Add( 1, 'abc' ) ) ; -- NG 型が違う

sys.put( Add.type_name() ) ;  -- func:Add を表示

引数の
型指定
-- 引数の型を決めて受け取る
func Sub
{
    a : int in[0] ; -- 引数を int 型に変換
    b : int in[1] ; -- int 型に変換できない引数は不可という意味に使う
    out : int a - b ;

    -- sys.put( in.type_name() ) ; -- arg[int,int,] を表示
    -- sys.put( in[0].type_name() ) ; -- int を表示
} ;

sys.put( Sub( 3, 5 ) ) ;           -- -2 を表示
sys.put( Sub( 3, 5 ).type_name() ) ; -- int を表示
sys.put( Sub( 1.2, 3.4 ) ) ;       -- NG real 型を int 型に変換できない
sys.put( Sub( 'abc', 'def' ) ) ;   -- NG string 型を int 型に変換できない

sys.put( Sub.type_name() ) ;  -- func:Sub を表示

◆ 参照(リファレンス)渡し

C/C++ や Java と違って Vino の関数への引数は常に参照(リファレンス)渡しなので注意が必要。
関数に配列を渡す際や、<<=(shift()) を用いて関数内で配列の個数を変更する際など、 更新可能な配列を渡すと都合の良い場合もある。

リファレンス渡し func AddTen
{
    in[0] += 10 ; -- int 10を足す

    sys.put( in.type_name() ) ;
    sys.put( in[0].type_name() ) ;
} ;

i $ 1 ;        -- 変数 $int 1 を宣言
AddTen( i ) ;  -- arg[$int,] $int を表示
sys.put( i ) ;    -- 11 を表示

i2 : 2 ;         -- 定数 int 2 を宣言
AddTen( tbl2 ) ; -- NG int は更新不可(定数)

r $ 10.0 ;    -- 変数 r $ real 10.0 を宣言
AddTen( r ) ; -- arg[$real,] $real を表示
sys.put( r ) ;   -- 20.0 を表示

コンテナを引数に渡す func ListAdd
{
    in[0] <<= 10 ; -- 配列に要素(int 10)を追加

    sys.put( in.type_name() ) ;
    sys.put( in[0].type_name() ) ;
} ;

tbl $ vector[int] 1, 2, 3, ; -- 更新可能なコンテナ vector[int]
ListAdd( tbl ) ;              -- arg[$vector[int],] $vector[int] を表示
sys.put( tbl.str() ) ;         -- 1,2,3,10, を表示

tbl2 : vector[int] 1, 2, 3, ; -- 更新不可なコンテナ
ListAdd( tbl2 ) ;              -- NG vector[int] は更新不可(固定コンテナ)

set1 $ set[int] 10, 20, 30, ; -- 更新可能なコンテナ set[int]
ListAdd( set1 ) ;              -- arg[$set[int],] $set[int] を表示
sys.put( set1.str() ) ;         -- 10,10,20,30, を表示

◆ 括弧()の省略
関数コールの括弧が省略できる。複雑な引数でなければ大抵の場合省略でき、見た目にもすっきり記述できる。

ちょっとまった。関数を呼ばずに引数に乗せたい場合と、関数を読んだ結果を引数に乗せたい場合と、どうやって区別する?
->引数であると確定したら関数は呼ばずに関数のまま引数に乗せる。

書き方 sys.put( 'ABC' ) ; -- sys.put( 'ABC' ) ; と同じ意味

-- aaa,bbb,ccc,ddd が関数名であった場合
aaa bbb ccc ddd ;    -- aaa( bbb( ccc( ddd() ) ) ) ; と同じ意味
aaa bbb, ccc, ddd ;  -- aaa( bbb(), ccc(), ddd() ) ; と同じ意味
aaa bbb, ccc ddd ;   -- aaa( bbb(), ccc( ddd() ) ) ; と同じ意味
-- しかし、可読性が悪くなるので推奨はしない。できるというだけ。



引数 Argument

引数の書き方は C/C++ とは大きく異なる。引数は argコンテナなので、argコンテナの宣言の変形であると認識してください。

予約語 in
引数
型指定
func Foo -- 引数が2つの場合
{
    in_a : int in[0] ; -- int 型で定数として受ける
    in_b $ int in[1] ; -- int 型で変数として受ける(変数であること)
    ...
} ;

con : 1 ; -- 定数 1
val $ 2 ; -- 変数 2

Foo( con, val ) ; -- OK
Foo( con, con ) ; -- NG in[1] が定数なので不可
Foo( val, val ) ; -- NG in[0] が変数なので不可
Foo( val.copy(), con.copy() ) ; -- .copy()すればOK

boo : 'boo' ; -- 定数 'boo'
woo $ 'woo' ; -- 変数 'woo'

Foo( boo, woo ) ; -- NG in[0] in[1] はstringなので不可

引数

未指定
func Foo -- 引数が2つの場合
{
    in_a : in[0] ; -- 型省略(どんな型でも可)、定数を受ける(変数は不可)
    in_b $ in[1] ; -- 型省略(どんな型でも可)、変数を受ける(定数は不可)

    sys.put( in_a.type_name() ) ;
    sys.put( in_b.type_name() ) ;
} ;

con : 1 ; -- 定数 1
val $ 2 ; -- 変数 2

Foo( con, val ) ; -- int $int と表示される
Foo( con, con ) ; -- NG in[1] が定数なので不可
Foo( val, val ) ; -- NG in[0] が変数なので不可
Foo( val.copy(), con.copy() ) ; -- .copy()すればOK int $int と表示される

boo : 'boo' ; -- 定数 'boo'
woo $ 'woo' ; -- 変数 'woo'

Foo( boo, woo ) ; -- string $string と表示される

◆関数も引数になる

複雑な記述になってしまうが、関数も関数の引数(arg配列)に載せられる。
特に Vino では引数の記述時に名前の無い関数をその場で記述できる特徴もある。

関数を引数に乗せる -- 関数(func{})も引数になる。
func
Foo
{
    -- 引数を関数( func{} 引数、戻り値ともに無し)として宣言する
    in_foo : func{} in[0] ;

    sys.put( in_foo.type_name() ) ;
    in_foo() ; -- 引数の関数をコール

} ;

-- 名前ありの関数を引数にのせる。

func Boo{ sys.put( 'BOO' ) ; } ; -- 関数 Boo を定義
Foo( Boo ) ; -- 関数 Boo を引数にのせて関数 Foo をコール。func:Boo{} BOO を表示

-- 名前なしの関数を引数にのせる。

Foo( { sys.put( 'NONAME' ) ; } ) ; -- 名前の無い関数を宣言して同時に引数にする。func{} NONAME を表示

-- さらに括弧も省略可能

Foo { sys.put( 'NONAME' ) ; } ; -- 名前の無い関数を宣言して同時に引数にする。func{} NONAME を表示


引数のある関数を引数に乗せる
func Woo
{
    -- 引数のある関数(func{in,out})も引数になる。
    in_woo : func{in:int,out:string,} in[0] ; -- 引数を関数(引数 int、戻り値string)として宣言(検査)する

    sys.put( in_woo.type_name() ) ; -- func{in:int,string,} を表示

    sys.put( "in_woo:" + in_woo( 100 ) ) ; -- 関数in_wooをコール
} ;

func Bar{ out : "<<{in[0] * 2}>>" ; } ;

Woo( Bar ) ; -- 引数に bar をのせて関数 woo() をコール。in_woo:<<200>> が表示される

Woo( { out : "**{in[0] + 50}**" ; } ) ; -- 名前の無い関数を定義して引数にのせる。
                   -- in[0] は 100 なので 150 を返し、in_woo:**150** が表示される

Woo { out : "{in[0] + 20}" ; } ; -- 関数コールの () を省略
                       -- in[0] は 100 なので 120 を返し、in_woo:120 が表示される



戻り値 Return Value

戻り値の書き方は C/C++ とは大きく異なる。これも argコンテナの記述の変形であると認識してください。

予約語 out nil
戻り値
1つ

func woo
{
    out : 0 ; -- 定数宣言すると値を返すことができる
    -- out m_return : 0 ; -- このように名前も付けられる
} ;

w : woo() ;        -- 関数を実行。結果を w に入れる。結果は arg[] 型になる
sys.put( w[0] ) ;  -- 10 を表示

sys.put( w.type_name() ) ;    -- int を表示
sys.put( w[0].type_name() ) ; -- arg[int,] を表示

戻り値
2つ

func
Foo -- 戻り値が2つ以上の場合
{
    out m_one : 10 ;
    out m_two : 20.0 ;
} ;
ret : Foo() ;
sys.put( ret.m_one ) ;  -- 10 を表示
sys.put( ret.m_two ) ;  -- 20.0 を表示
sys.put( ret[0] ) ;     -- 10 を表示
sys.put( ret[1] ) ;     -- 20.0 を表示

sys.put( ret.m_one.type_name() ) ; -- int を表示
sys.put( ret.type_name() ) ;       -- arg[m_one:int,m_two:real,] を表示

◆スコープでも名前無しの関数と同じ

関数名なし -- スコープというより名前のない関数宣言&実行後インスタンスをaに代入です
a : { out : 100 ; out : '200' ; } ; -- a : arg[] 100, '200', ;

sys.put( a[0] ) ;             -- 100
sys.put( a[1] ) ;             -- 200
sys.put( a[0].type_name() ) ; -- int
sys.put( a[1].type_name() ) ; -- string
sys.put( a.type_name() ) ;    -- arg[int,string,]

関数名あり -- こっちは名前あり関数宣言&実行後インスタンスをaに代入です
a : func F{ out : 100 ; out : '200' ; } ;

sys.put( a[0] ) ;             -- 100
sys.put( a[1] ) ;             -- 200
sys.put( a[0].type_name() ) ; -- int
sys.put( a[1].type_name() ) ; -- string
sys.put( a.type_name() ) ;    -- func:F{int,string,}


3章につづきます。


Vino言語(1/4) (2/4) (3/4) (4/4)

last update 2003/02/06
since 2002/09/16



やまざきのおすすめエレクトロニクス


やまざきのおすすめ本

やまざきのおすすめDVD

やまざきのおすすめCD



Copyright(c) 1998-2006.
YAMAZAKI Satoshi.
All rights reserved.

since 1997/12/15


このページのURLをメールで送る(友人・知人に教えてあげる)
このページを「お気に入り」に追加する(忘れないように…)
● お手紙はこちら↓。仕事の話は大歓迎です。(忙しくて返信できなかったらごめんなさい。)