Rubyにおける一般のブロック内でのnext/break(終了?)

繰り返しではないブロック内で next/break ができるのって 気持ち悪くない?という @kmizu さんの呟きからの議論(と茶々)。 まとめ作成者注: Rubyでは (0..10).each {|i| puts i} のように メソッド(この場合はRange#each)がコードブロックを引数に取ることができます。このコードブロックは上記のように繰り返しに使われることが多かったため「イテレータ」と呼ばれていました。 続きを読む
7
前へ 1 2 ・・ 16 次へ
kmizu @kmizu

@_ko1 んー。あまりにダメというのがわからないです。説明がうまく無いだろうとは思いますが。

2012-05-21 15:05:30
Shugo Maeda @shugomaeda

@kmizu ちなみに、nextにはlambdaでないブロックからreturnしようとするときにreturnの代りに使うという用途があります

2012-05-21 15:06:57
成瀬 @nalsh

@_ko1 @kmizu 歴史的には当初イテレータともっぱら呼ばれていたけれど、繰り返さないことが多くなってきたので、あまりイテレータとは呼ばれないようになり、代わりにブロックって呼ばれるようになったんだったような

2012-05-21 15:07:34
_ko1 @_ko1

@kmizu イテレータで使うことはわかるのに,イテレータと関係無い,っていうのは変だろう.

2012-05-21 15:07:39
Shugo Maeda @shugomaeda

@nalsh @_ko1 @kmizu 厳密にいうと、イテレータはブロックを取るメソッド(のうち繰り返すもの)だからささださんの説明もダメだと思う

2012-05-21 15:08:29
_ko1 @_ko1

@shugomaeda @nalsh @kmizu いや,俺イテレータって言葉を(引用以外で)使ってないよな.

2012-05-21 15:10:01
kmizu @kmizu

@_ko1 いや、そんなことは言ってません。そりゃ関係あるに決まってますよ。自分が言ったのは「イテレーション」(=繰り返し)と関係なくbreak/nextの意味は定義される、という事です。繰り返しと素直に書けばよかったので、そこは申し訳なかったですが。

2012-05-21 15:12:28
_ko1 @_ko1

@shugomaeda @nalsh @kmizu あ,最初に俺がイテレータと書いてたんだ.すみませんすみません

2012-05-21 15:13:51
_ko1 @_ko1

@kmizu いや,言いたいことはわかってるんだけど.途中で用語の揺れがあって,そこでなんか破綻していた

2012-05-21 15:14:54
_ko1 @_ko1

@kmizu ちなみに,まぁ open{} は 1.times{} と書いてあると思えばそんなに違和感は

2012-05-21 15:16:35
kmizu @kmizu

@_ko1 んー、用語の揺れは申し訳ないです。つまり、ユースケースの話じゃなくて、言語のプリミティブの意味論の話をしている、というのはわかってたということでよいでしょうか。

2012-05-21 15:16:45
kmizu @kmizu

@_ko1 まあ、そういう考えはありだと思います。

2012-05-21 15:18:31
成瀬 @nalsh

ブロックはループの抽象化よりいでてCLUよりオブジェクト指向っぽい

2012-05-21 15:19:26
_ko1 @_ko1

@kmizu 実装によっては,open(){ ... } のブロックが繰り返して見たり(トランザクション的な)するかもしれないので,とかなんとか 実行時に break とか next が使えなくなるよりは,レキシカルに決まる方がわかりやすいんじゃないかな

2012-05-21 15:19:40
_ko1 @_ko1

@kmizu 実行時にメソッドによって,だった.

2012-05-21 15:20:14
kmizu @kmizu

@shugomaeda なるほど。nextがブロックの呼び出しからの脱出であるので、そういう使い方もできるわけですね。

2012-05-21 15:20:36
_ko1 @_ko1

@kmizu しかし,return はレキシカルに決まらないんだよな....ダメな気がする.

2012-05-21 15:21:56
kmizu @kmizu

@_ko1 はい。そこは異論無しです。レキシカルにブロックの中なら break/next 使える、というルールの方がシンプルでわかりやすいと私は思います。

2012-05-21 15:24:46
kmizu @kmizu

@_ko1 その辺、Scalaで無名関数からreturnしたとき、似た挙動するのですが、そこはちゃんとレキシカルにreturn先が決まるようになってますね。Scalaだとネスドしたメソッドが書けるので、return先がdynamicに決まると困るという話ですが。

2012-05-21 15:30:58
_ko1 @_ko1

@kmizu Ruby だと lambda か Proc かで意味が変わってしまうという 酷い挙動なので何とかして欲しい

2012-05-21 15:36:08
kmizu @kmizu

ちょっと言いたかったことを整理し直す。まず、特にC系(/C++/C#/Java)言語においては、break/continue は、言語の繰り返し処理用プリミティブ (while, for, do-while)(cont) http://t.co/LAoWoE86

2012-05-21 15:46:22

まず、特にC系(/C++/C#/Java)言語においては、break/continue は、言語の繰り返し処理用プリミティブ (while, for, do-while) と対応する形で意味が定義されていた(switchは例外)。一方、Rubyでは、ブロックという(機能的にはちょっと変わった無名関数)もっと汎用的なプリミティブに対して break/next(continue的なもの)が定義されている。break/nextというキーワードは明らかに繰り返しを想起させるものであるにも関わらず、それらの意味は実際には繰り返し処理と直接関係が無い。

結論としては、繰り返しを想起させるキーワードを使った言語プリミティブの動作が、繰り返し処理とは意味的には関係ないことが気持ち悪い。実用的にはbreak/nextは繰り返し処理に対して使われる事が多いし、それ以外の変な使い方をする人はまず居ないので問題にはならないだろう。でも、キーワードと意味にずれがあるのがもにょる。

と、こういう話です。


Shugo Maeda @shugomaeda

@kmizu メソッドは0回以上ブロックを実行(yield)する。ブロック中のnextはyield元のメソッドに戻って次の処理をする。ブロック中のbreakはyield元のメソッドを中断する。と考えると、next/breakの意味はそんなにおかしくない気もしますがどうでしょうか

2012-05-21 16:33:00

↓余談

前へ 1 2 ・・ 16 次へ