[過去ログ] 次世代言語11[Rust Swift TypeScript Dart] (1002レス)
前次1-
抽出解除 レス栞

このスレッドは過去ログ倉庫に格納されています。
次スレ検索 歴削→次スレ 栞削→次スレ 過去ログメニュー
844
(6): デフォルトの名無しさん [sage] 2018/06/30(土) 23:16:50 ID:tr0WXiW5(2/2) AAS
>>837
837(4): デフォルトの名無しさん [sage] 2018/06/30(土) 16:41:24 ID:oxrLiD+S(1) AAS
るびぃ信者、Proc.new、ラムダ、ブロックにおけるreturn、break、nextの挙動の違いをまとめようとした模様
外部リンク:qiita.com

結果、ややこしすぎるためコーディングを工夫してreturnやbreakの使用を避けましょうというなんじゃそりゃな結論www

何か理由があってわざわざ挙動を変えたんだろうが(まさか行き当たりばったりってことはないよね笑)ややこしすぎで使用自体を避けられてちゃ本末転倒だよなwww
Ruby のProc, block はクロージャだから、クロージャを囲む関数から戻る。
一方ラムダは、単にクロージャを抜けるだけ。
Groovy なども参照

def f
(0..5).each do |i|
puts i
return if i == 3
end
end

f() #=> 0, 1, 2, 3
848
(1): 844 [sage] 2018/07/01(日) 02:00:27 ID:YZ+qvhoO(1/2) AAS
クロージャは、クロージャの外側の環境をつかんでいる。
つまり、クロージャを囲む関数内の変数をつかんでいる

だから、クロージャ内でreturn すれば、外側の関数も抜けて、
関数内の変数なども、解放した方が良いと考えた

Groovy の挙動とは違うかも
852
(2): 844 [sage] 2018/07/01(日) 08:32:31.95 ID:YZ+qvhoO(2/2) AAS
クロージャ(block)内のbreak は、クロージャを抜けるだけで、外側の関数は抜けない。
関数の最後まで実行される

クロージャ内のnext は、次の繰り返しに進むだけで、クロージャも抜けない。
クロージャの最後まで実行される

def f
num = 0
(0..5).each do |i|
num = i
break if i == 3
end
puts num
end

f() #=> 3
864
(1): デフォルトの名無しさん [sage] 2018/07/01(日) 10:59:11.30 ID:uHA6sqOS(1) AAS
>>844はクロージャなら当然あるべき姿としてRubyのProcを語ってるからなぁ

それに対して>>847
847(4): デフォルトの名無しさん [] 2018/07/01(日) 01:54:08 ID:5prQoZWD(1/8) AAS
>>845
ヒント:Smalltalk
がヒント:Smalltalkって言ってるのは
要するにSmalltalkがクロージャのあるべき姿を体現してるって言ってるワケで、そりゃ傲慢すぎる

ただの一例としてSmalltalkのような仕様もあるって言うなら批判されないのに
899: デフォルトの名無しさん [sage] 2018/07/01(日) 20:00:26.61 ID:e+fGbKAY(2/2) AAS
>>862
862(3): デフォルトの名無しさん [] 2018/07/01(日) 10:45:16.40 ID:QlwNZjji(2/5) AAS
Smalltalkの人たちはScalaやRustのtraitsに対して、オリジナルのSmalltalkと違うからダメだ!あれは別物!って批判するくせに
他の言語より後に実装したclosureについては独自仕様でも問題ない、技術ベースで語れっておかしくね?
ダブスタも甚だしいだろ
> 他の言語より後に実装したclosureについては独自仕様でも問題ない、技術ベースで語れ

私はSmalltalk信者wですが、この文脈での>>844の「クロージャだから」もそれを受けた>>847の「ヒント:Smalltalk」も
混乱を招きかねない説明やサジェスチョンだと思いまよ。

# 以下は比較的に古典的かつナイーブな実装の Squeak や Pharo を想定しています。為念。

Ruby の retrun に相当する Smalltalk の(唯一の)制御構造である「^戻り値」は、
Ruby の>>837の例では prco_return や block_retrun と同じ挙動になります。

Object compile: 'rubyReturn
 | f ret |
 f := [:n | ^ n * 10. "以降に処理を書くとコンパイル時エラー"].
 ret := #(1 2 3) collect: f.
 ^''ret: '', ret printString'.

self rubyReturn "=> 10 "

余談ですが、lambda_return の挙動も「thisContext retrun」(戻り値が欲しいときは「return: 戻り値」)
という表現を使えばまあできなくはないです(が普通はやりません)。

Object compile: 'rubyLambdaReturn
 | f ret |
 f := [:n | thisContext return: n * 10. #以降の処理は無視].
 ret := #(1 2 3) collect: f.
 ^''ret: '', ret printString'.

self rubyLambdaReturn "=> 'ret: #(10 20 30)' "

いずれにせよ、Smalltalk でクロージャ内のリターンがそのクロージャを実行中のメソッドコンテキストを抜けるという挙動をもって
(継続渡しとかならともかく)Ruby の複雑な状況の説明を試みるのはあまりよい方法ではないのは確かですね。
912
(1): 844 [sage] 2018/07/02(月) 06:42:05.84 ID:9wGdj7CA(1) AAS
>>857
857(8): デフォルトの名無しさん [] 2018/07/01(日) 09:23:49.76 ID:FQlsc9Xo(2/5) AAS
>>852
あなたが closure だからと主張する、block は 952の挙動だが Proc では break は例外吐くらしいけど何で?

# 言っちゃ悪いが、closure は定義した時点での環境を基準に動作が普通だと思うんで、
# ループ外で定義されているならば next/break は一律例外吐くで無いと一貫性がないようにしか見えん。
Ruby のProc, block はクロージャで、
Procは、blockを変数に入れて、持ち運んで、後で呼べるようにしたもの

その際、block内でbreak を呼ぶと、ループ処理が完遂せず、失敗とみなしたのだろう

ラムダは後に作られたから、return で値を返すようにした

結局、Proc, block、ラムダ、クラス・モジュールも、
スコープチェーンという単一の概念から出来ている

自分の1つ外側のスコープを指す、ポインタを持っている
938
(1): 844 [sage] 2018/07/03(火) 01:06:30.72 ID:LtnxPY8P(1) AAS
Ruby では、break, return、例外も、単一の同じ仕組みを使っている。
コールスタックをさかのぼるポインタ。
つまり、どこから呼ばれて、どこへ戻るか

breakは、1つ外側のスコープへ戻る。
returnは、最も外側のスコープを抜ける

(レキシカル)スコープチェーンと、コールスタックの2大柱。
実装系・VM を作るには、この本がおすすめ

Rubyのしくみ、2014
Rubyの実装系、Ruby1.9のRuby仮想マシンの内部の仕組み
前次1-
スレ情報 赤レス抽出 画像レス抽出 歴の未読スレ AAサムネイル

ぬこの手 ぬこTOP 1.483s*