組み込みC言語プログラマのためのmruby入門(中編) ―― mrubyをお手軽に体験する!
●複数の値を返すメソッド
C言語では,関数からの返り値は一つで,複数の値を戻す場合には,引き数にポインタを使うか,構造体を返り値にする必要があります.Rubyではメソッドから複数の値を返すことができ,また複数の値を代入することができます.
>> def sample(x)
>> return x, x * 10, "hello"
>> end
=> nil
>> a, b, c = sample(5)
=> [5, 50, "hello"]
>> a
=> 5
>> b
=> 50
>> c
=> "hello"
C言語よりも簡潔に複数の値を返せることがお分かりいただけると思います.
●ブロック付きメソッド呼び出し
Rubyのメソッド呼び出しでは,メソッド中から呼び返すための処理単位を付加することができます.この処理単位をブロックと呼びます.これは,C言語の関数にはない機能です.C言語でも,関数ポインタを用いたコールバックを行うことで類似の機能を実現できますが,Rubyではより可読性を向上し,安全に実行できます.慣れるまで面食らいますが,なかなか便利な機能です.
ブロック付きメソッド呼び出しを行うメソッドには,yield文を仕込んでおきます.メソッド中でyield文が呼ばれると,その時点でメソッド中の処理を中断して,ブロックの処理を行います.
> def loop(x)
* for i in 0 .. x do
* yield i
>> end
>> end
=> nil
ブロック付きメソッド呼び出しは,以下のように記述します.ブロックは,例外処理などと同様にbegin~endでくくるか,リストにあるように波かっこ( { } )でくくります注3.
注3:厳密に言うと,begin~endと { } では文法解釈時の結合強度に違いがある.違いが分からない場合は, { } でくくることをお勧めする.
>> loop(5) {|c| puts c}
0
1
2
3
4
5
=> 0..5
メソッドloop中の「yield i」で引き数となっている変数iの内容は,ブロック中の変数cに代入されます.ブロック中でputsを実行した後,制御はメソッドloopに戻り,「yield i」の次の行から再開されます.
ブロック付きメソッドは,メソッドの実装者が処理の枠組みだけを提供できる点でとても有用です.上記の例では,メソッドloopには「0からxまで繰り返し何かを呼び出す」ということのみ記述されており,細かい処理はloopを呼び出す側に任されています.見方を変えると,呼び出し側はメソッドの実装をいじることなく,処理の内容を柔軟に変更できます.
処理を中断して別の処理を行うという,組み込みソフトウェアの割り込み処理のような内容から想像できると思うのですが,このyield文周りと例外処理のからみで,初期のmrubyにはたくさんのバグがありました.本稿執筆時点では多くが修正されているはずですが,本質的に実装が難しい類の処理です.
あらゆる処理の組み合わせでも安心して使えるようになるには,しばらく時間がかかる可能性はあります.それでもなお,使うメリットがある機能ではあります.