RubyのBreak Statementは、Proc.newv。TheAmpersand Signを使用するときに異なって振る舞うのですか?

StackOverflow https://stackoverflow.com/questions/8888958

  •  29-10-2019
  •  | 
  •  

質問

ブロックのブレークステートメント(ASに基づいて Rubyプログラミング言語)は次のように定義されています。

ブロックはそのiteratorに戻り、イテレーターはそれを呼び出した方法に戻します。

したがって、次のコードが実行されると、LocalJumperrorになります。

def test
    puts "entering test method"
    proc = Proc.new { puts "entering proc"; break }
    proc.call # LocalJumpError: iterator has already returned
    puts "exiting test method"
end
test

次のコード ではない LocalJumperrorを投げます。 Ampersand Signの特別なことは何ですか?アンパサンドは、暗黙的にproc.newを使用していませんか?

def iterator(&proc)
    puts "entering iterator"
    proc.call # invoke the proc
    puts "exiting iterator" # Never executed if the proc breaks
end

def test
    iterator { puts "entering proc"; break }
end
test

言い換えれば、私はAmpersand SignをProc.Newの呼び出しに携わる手段として読みます。その時点で、動作は最初のコードスニペットとまったく同じでなければなりません。

def iterator (p = Proc.new { puts "entering proc"; break})
...
end

免責事項: :私は言語を学んでいるNewb(Ruby 1.9.2)であるため、参照と詳細な概要を高く評価します。

役に立ちましたか?

解決

break ブロックを作成します 発信者 ブロックリターンの。次のコードで:

proc = Proc.new { break }

Procオブジェクトに変換されるブロックの「発信者」はproc.newです。 break ブロックの発信者に戻ることになっていますが、Proc.Newはすでに返されています。

このコードで:

def iterator(&b); b.call; end
iterator { break }

ブロックの発信者はです iterator, 、だからそれは作ります iterator 戻る。

他のヒント

これが次のとおりです 答え.

Ampersandは、Procをブロックに、ブロックをProcに変換するために使用されます。

私はあなたのケースに関連するように例を変更しました:

def run_my_code(&my_code)
 puts 'before proc'
 my_code.call
 puts 'after proc'
end
run_my_code { puts "passing a block, accepting a proc"; break}
=> before proc
   passing a block, accepting a proc

ご覧のとおり、「後のProc」に到達しませんでした

def run_my_code
 yield
end
my_proc = Proc.new  { puts "passing a proc instead of block"; break}
run_my_code &my_proc
=> passing a proc instead of block
   LocalJumpError: break from proc-closure
   from (pry):75:in `block in <main>'

2番目の例では、結果がprocがあります。 iterator に戻ります test 関数。

def iterator(&proc)
  puts 'entering iterator'
  proc.call
  puts 'exiting iterator'
end

def test
  puts 'before test'
  iterator { puts 'entering proc'; break }
  puts 'after test'
end

=>before test
entering iterator
entering proc
after test

ブロック、Procs、Lambdasの違い、およびそれぞれのスコープに関係しています。

私はあなたが役に立つかもしれないと思うかもしれないという2009年にそれについての投稿を書きました: http://www.leonardoborges.com/writings/2009/07/22/procs-lambdas-blocks-whats-the-difference/

お役に立てれば。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top