Ruby の next 、ついでに Perl も
Ruby の next は引数を取れる
next はループのなかで使って、後続の処理をスキップして次のターンに行くというのが役割だと思っていたけど、Ruby では yield 呼び出しの脱出にも next を使う。
nextはもっとも内側のループの次の繰り返しにジャンプします。 イテレータでは、yield 呼び出しの脱出になります。 next により抜けた yield 式は nil を返します。 ただし、引数を指定した場合、yield 式の戻り値はその引数になります。
http://docs.ruby-lang.org/ja/2.1.0/doc/spec=2fcontrol.html#next
なるほど〜
たしかに言われてみれば自然。でもループっぽくないブロックもあるから、今日ちょっと「あれっ?」と思ったのだった。
何の意味もないけど、適当にこういうコードを書いて実行してみる。
#!/usr/bin/env ruby class Foo def self.bar(n) (1..n).each do |i| ret = yield i p ret break if ret == 'hi' end end end Foo.bar(10) do |i| next 'hi' if i == 3 end
出力結果はこうなる。
nil nil "hi"
ふむふむ。
一方 Perl では
Perl でも next に引数を指定できる。
next LABEL
http://perldoc.perl.org/functions/next.html
これはループの先頭にラベルを付けておいて next LABEL
とすると、ネストしたループの中からラベルのついたループまで脱出できるというやつだ。それは知っていたけど、ひさしぶりにドキュメントみたらこういうのを見つけた。
The next EXPR form, available as of Perl 5.18.0, allows a label name to be computed at run time, being otherwise identical to next LABEL .
つまり、next の引数に式を指定できて、その評価結果がラベルとして使われるようだ。5.18.0 から。
試しに以下のようなコードを書いてみたけど、もはや何がしたいのかわからなくなってきた。
#!/usr/bin/env perl use strict; use warnings; LINE: while (my $line = <>) { chomp($line); print "line: $line\n"; FIELD: foreach my $field (split /,/, $line) { next uc($field) if $field =~ /\A(?:line|field)\z/; print "field: $field\n"; } }
実行すると標準入力を1行ずつ受け取って while ループが実行される。 実行結果はこんな感じになる。
aaa,bbb,ccc line: aaa,bbb,ccc field: aaa field: bbb field: ccc aaa,line,ccc line: aaa,line,ccc field: aaa aaa,field,ccc line: aaa,field,ccc field: aaa field: ccc
おわり。