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

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

とりあえず、スレッドがあまりにも長く、議論が堂々巡りになっている部分もあるので、以下に私が(議論の途中までを)解釈した内容をまとめます。
↓↓↓↓

NaOHaq(苛性ソーダ) @NaOHaq

自分の理解の整理 (1) Rubyにおける break, next の意味論(semantics) ≒ 挙動は、見た目の字面に反して、ループというイディオムとは独立に記述できる。 #ruby_break_next

2012-05-22 12:23:15
NaOHaq(苛性ソーダ) @NaOHaq

(2) 当初の設計意図から離れて「ブロック付きメソッド呼出し」という機能を観察すると、メソッドは高階関数、ブロックはそこに渡す無名関数、nextは無名関数からのreturn、breakはメソッドからの大域脱出として記述することができる #ruby_break_next

2012-05-22 12:27:11
NaOHaq(苛性ソーダ) @NaOHaq

論点整理 (3)ただし、「ブロック付きメソッド呼出し」を「ループの抽象化」と捉えた場合、next と break はループに深く関連した性質を持っていると理解できる #ruby_break_next

2012-05-22 12:44:52
NaOHaq(苛性ソーダ) @NaOHaq

(4) 一方、設計当初は「ループの抽象化」のために用意された「ブロック付きメソッド呼出し」はループ以外の場面でも広く使われており、そのような場面では next, break は(2)のような性質のプリミティブとして振舞う #ruby_break_next

2012-05-22 12:48:06
NaOHaq(苛性ソーダ) @NaOHaq

(5) (@kmizuさんの違和感1)他の言語(というかCやJava)をみたとき、ループ制御構文のbreakやcontinueはfor,whileというプリミティブと対応しているが、Rubyのnext,breakには対応するプリミティブがない #ruby_break_next

2012-05-22 12:54:54
NaOHaq(苛性ソーダ) @NaOHaq

(6) 5に対する @shugomaeda さんの意見: 繰返しを内部イテレータとして抽象化すると必然的に高階手続き的なものになるのでは(例: CLUのfor) https://t.co/fm1SU7PB #ruby_break_next

2012-05-22 13:14:03

↑↑↑↑
とりあえず 2012/05/22 10:39 くらいまでの流れがこんな感じ


以下本編

kmizu @kmizu

open(fname){|f| next puts f.read } とかしたら、まあ何も出力されないし、理由もわかるけどなんか気持ち悪いよね。

2012-05-20 20:47:38
kmizu @kmizu

@_ko1 通常、break/next はループからの脱出/継続が想起されるものですよね(Rubyのそれは意味的にはそれと直接対応しませんが)。Cで言うと、 { ...; continue; } ができてしまう(出来ないですが) ような気持ち悪さというか。

2012-05-21 00:19:16
_ko1 @_ko1

@kmizu んー,よくわからない.何か前提があるんだろうけど.ちなみに,表示はされた.

2012-05-21 06:53:46
kmizu @kmizu

@_ko1 あれ?こちらの環境だと表示されなかったのですが。あ、Twitterに投稿するときに改行消えちゃってたのですね。 open(...){ |f| next; puts f.read } が意図してたものです。

2012-05-21 14:51:31
_ko1 @_ko1

@kmizu それだと出ないね.だけど,Ruby を知っているからか,それでダメ名理由がわからない.C でも continue したら表示されないよな(単に unreachable code なだけで)

2012-05-21 14:53:22
kmizu @kmizu

@_ko1 まず、多くの言語におけるbreak/continueのようなのは、それに対応するwhile/for等の言語のループ用の*プリミティブ*の中でしか使えないですよね。一方、Rubyのbreak/nextは「ループ」とは意味的に全く関係ない(そういう風に使えるとはいえ)。

2012-05-21 14:53:47
kmizu @kmizu

@_ko1 Cだとそもそもループ(for, while) or switch 外でbreak/continueはコンパイルエラーですよね(なんかの独自拡張は知りません)。というか試しました。

2012-05-21 14:55:43
_ko1 @_ko1

@kmizu ブロックは別名,イテレータという

2012-05-21 14:56:53
kmizu @kmizu

@_ko1 はい。元々の経緯はある程度知っています。でも、それは関係ないですよね。break/next のセマンティクスはイテレーションとは関係ない。

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

@kmizu ? イテレーションから next とか break とかしたいよね?

2012-05-21 14:59:55
kmizu @kmizu

@_ko1 もちろん。しかし、イテレーションと関係なく next とか break の意味論は定義される。

2012-05-21 15:01:27
_ko1 @_ko1

@kmizu え,イテレーションを便利にするために next とか break は定義されてるよねえ

2012-05-21 15:02:19
Shugo Maeda @shugomaeda

@_ko1 @kmizu 繰り返し以外の用途(常に一回だけ呼び出す)で使われることが多くなったから、そういう時は気持ちわるいという話じゃないですかね。で、そういう時はあまりnext/break使わないので実用上はみんな困ってないんじゃないかと

2012-05-21 15:02:50
kmizu @kmizu

@_ko1 ちょっと話がずれてる気がして来たのですが、Rubyのブロック内でnextとかbreakしたい理由は当然理解しています。自分がキモいと思うのは、next/breakのセマンティクスの話であって、それが要らないというわけじゃないです。

2012-05-21 15:03:04
_ko1 @_ko1

@shugomaeda @kmizu いや,わかってんだけど @kmizu の説明があまりにダメなので

2012-05-21 15:03:41
kmizu @kmizu

@shugomaeda はい。実用上はまず困らないだろうと思います。自分も、イテレータ的でないものの中でnext/break使おうと思いませんし。

2012-05-21 15:04:43
1 ・・ 16 次へ