Techioz Blog

予期しないリターン (LocalJumpError)

概要

この Ruby 2.0 コードにはどのような問題があるのでしょうか?

p (1..8).collect{|denom|
    (1...denom).collect{|num|
        r = Rational(num, denom)
        if r > Rational(1, 3) and r < Rational(1, 2)
            return 1
        else
            return 0
        end
    }
}.flatten
エラーは

のブロック (2 レベル) にあります: 予期しない戻り (LocalJumpError)。 n 個の 1 (および残りの 0) を含むフラット リストを作成したいと考えています。ここで、n は分母が 8 未満で 1/3 から 1/2 までの有理数の数です。 (これはプロジェクト オイラーの問題です)。なのでインナーブロックから戻ろうとしています。

解決策

Ruby* ではブロック内に戻ることはできません。最後のステートメントが戻り値になるため、この場合は return ステートメントを削除するだけです。

p (1..8).collect{|denom|
    (1...denom).collect{|num|
        r = Rational(num, denom)
        if r > Rational(1, 3) and r < Rational(1, 2)
            1
        else
            0
        end
    }
}.flatten

*: lambda ブロック内で次のように実行できます: lambda { return “foo” }.call # => “foo”。これはスコープ設定などに関係しており、これがラムダ ブロックと proc ブロックの主な違いの 1 つです。メソッドに渡す「通常の」ブロックは、proc ブロックに似ています。