1.8

2009-07-05 8 views
2
ルビー1.8(私のバージョンは1.8.7-72である)、このコードで

1.8

foo = lambda do 
    for j in 1..2 
    return 
    end 
end 
foo.call 

クラッシュLocalJumpError有する:

test2.rb:3: unexpected return (LocalJumpError) 
    from test2.rb:2:in `each' 
    from test2.rb:2 
    from test2.rb:6:in `call' 
    from test2.rb:6 

なぜこれはこれをしますか?しかし、それはRuby 1.9の私のバージョンで正常に動作するようです。

編集:ラムダの中に戻るだけではありません。次のように動作します。

foo = lambda do 
    return 
end 
foo.call 

答えて

8

何が起こっているのかは、ラムダの途中のfor文が内部的にブロックに変換されることです。 Rubyでは、ブロック内のreturnステートメントはその囲みメソッドにスコープされます。次の点を考慮return全体bar方法にスコープされているため

def bar 
    foo = lambda do 
    for j in 1..2 
     return j 
    end 
    end 
    foo[] 
end 
p bar 

barを実行し、1は、返されます。ブロックから戻るには、どちらもパラメータを取るnextまたはbreakを使用します。以下を検討してください。

def bar 
    foo = lambda do 
    for j in 1..2 
     break j 
    end 
    end 
    foo[] + 1 
end 
p bar 

このブレイクはあなたをブロックから戻し、以降の反復をブロックします。この場合、イテレータは1を返し、foo[] + 12を返すので、barを呼び出すと2が返されます。

すべてが混乱している場合、ブロック内での戻りは周囲のメソッドにスコープされ、周囲のメソッドがない場合はLocalJumpErrorが発生します。あなたはスロー/キャッチで

foo = lambda do 
     catch(:escape) do 
      for j in 1..2 
      throw :escape 
      end 
      # other code that won't get run 
     end # catch(:escape) 
     end # lambda 

throwをループし、ラムダの残りの部分を逃れることができ

+0

代わりにラムダの範囲を指定できないのはなぜですか?元のシナリオでは、私はスキップする必要があるforループの後にコードがあるので、ループから抜け出すことはできません – user102008

+0

ラムダではなく、実際の方法を試すことができます。 –

+0

Damn。 Ruby 1.8では、define_methodで定義されたメソッドの内部からproc内からの戻りは許可されません。それを傷つける。 –

0

はまた、あなたが値を返すために使用することができ、オプションの二PARAMTERをとります。

+0

これはリターンをエミュレートするかなり重い解決策だと私は思います。 –

+0

戻り値を返すための他の多くのオプションはありません(他のオプションは例外とcallccです)。私は選択肢が最も軽いと思う。最善の解決策はおそらくちょうどメソッドを使用していますが、これを閉じる必要があるスコープがそれにうまく対応しない場合は、これは扱いにくいことがあります。これはラムダから戻ることを許す1.9がいい理由です。 –

+0

Ruby 1.8でRuby 1.9のlambdaをエミュレートする方法を追加しました。私の答えはthrow/catchよりも軽量です。 –