begin ... end
と (...)
は例外処理の可否を除いて同じ動作だと思っていたが違った。
きっかけは、C言語でいう do { ... } while(0);
(ブロックを1回だけ実行)をRubyで試したこと。
puts "example 1" while false
(
puts "example 2"
) while false
begin
puts "example 3"
end while false
example 3
Rubyにおいては例1,2の動作が自然だと思っていたので、C言語の例のようなことはできないと思っていたが、例3の通り begin ... end
なら問題なく中身が実行された。
文法の仕様確認
JIS X 3017 を確認してみたところ、意外なことに処理系定義だった。
12.5 while 修飾文
構文規則
《while修飾文》 ::
《文》 [《行終端子》禁止] “while” 《式》意味規則
S “while” E という形式の《while 修飾文》(ここで,S は《文》,E は《式》とする。)は,次の手順で評価する。
a) S が《begin 式》の場合,動作は処理系定義とする。
b) “while” E “do” S “end” という形式の《while 式》を評価する。
c) 評価結果の値を,《while 修飾文》の値とする。
処理系定義の場合は動作をドキュメントに書かなければならないらしい。Rubyリファレンスマニュアルを見たら、確かに明記されていた。
while 修飾子
例:
sleep(60) while io_not_ready?
文法:
式 while 式
右辺の式を評価した値が真の間、左辺を繰り返し実行します。
左辺の式が begin 節である場合にはそれを最初に一回評価してから繰り返します。
例:
send_request(data) begin res = get_response() end while res == 'Continue'
while 修飾した式は nil を返します。 また、引数を伴った break により while 修飾した式の戻り値をその値にすることもできます。
他の場合
仕様を見たら明らかだが、
- until修飾子も
begin ... end
に対しては処理系定義 - if修飾子、unless修飾子は特別扱いなし(これは当然だろう)