4

私の理解ではif、行末のステートメントは行頭のコードの前に評価されます。

'never shown' if (false)

そして代入はifステートメントで可能です。

'shown' if (value = 'dave is king')
value #=> "dave is king"

そして、存在しない変数が代入されると、それが作成されます。事前に存在する必要はありません。これは本当ですか?

これらの仮定がすべて正しい場合、なぜこれが失敗するのでしょうか?

error_array << error if (error = import_value(value))
#=> undefined local variable or method `error' for

配列が右にプッシュされる前にエラーに割り当てられましたか? 物事がいつ評価されるかを理解したい。

これは機能します:

if (error = import_value(value))
  error_array << error
end

今、私は本当に混乱しています。

4

3 に答える 3

5

関数を呼び出すと、リテラル値を割り当てようとしたときにのみ発生します。

def foo(a)
  a
end

p 'not shown' if(value = foo(false))
p 'shown' if(value = foo(true))

# This outputs a Warning in IRB
p 'shown' if(value = false)
(irb):2: warning: found = in conditional, should be ==

デバッグをオンにすると (-d)、使用されている変数に関する警告が表示されますvalue

warning: assigned but unused variable - value

trueこれは、ステートメントが関係する限り評価され、その前のコードを実行できるため、「機能します」 。

ここで起こっているのは、修飾子として使用された場合の if() には、独自のバインディング スコープまたはコンテキストがあるということです。そのため、代入は if の外では見られないため、実行しても意味がありません。if ステートメントが取るブロックも割り当てと同じスコープ内にあるため、これは if 制御構造とは異なりますが、if 修飾子の前の行は if のスコープ内にありません。

つまり、これらは同等ではありません。

if a = some(value)
  puts a
end

puts a if(a = some(value))

前者puts aはifのスコープ内に、後者puts aはスコープ外にあり、異なる束縛(Rubyがコンテキストと呼ぶもの)を持つ。

Ruby の操作順序

于 2013-02-27T02:04:38.547 に答える
4

Ruby では、ローカル変数はパーサーが最初に代入に遭遇したときに定義され、その時点からスコープ内にあります。Ruby は英語のように左から右、上から下に解析されるため、ローカル変数を使用するときにはまだ存在しません。

ここに少しデモンストレーションがあります:

foo # NameError: undefined local variable or method `foo' for main:Object

if false
  foo = 42
end

foo # => nil

ご覧のとおり、 4 行目の代入は実行されていませんが、ローカル変数は7 行目に存在します。ただし、解析されたため、ローカル変数fooが存在します。しかし、代入は実行されなかったため、変数は初期化されておらず、評価結果はniland notになり42ます。

次に、ケースの最も単純なバージョンに進みましょう。

bar if bar = true
# warning: found = in conditional, should be ==
# NameError: undefined local variable or method `bar' for main:Object

bar # => true

割り当てが解析されると、変数が作成されます。これは次のとおりです。

bar if bar = true
       ^^^^^^^^^^

しかし、ここで使用されます:

bar if bar = true
^^^

これは割り当ての前です。ここでは解析が関連しているため、割り当てが使用前に実行されるという事実は無関係であり、使用のに割り当てが解析されるため、使用の時点でパーサーはまだ引数リストのないメソッド呼び出しであり、暗黙的であると考えています。ローカル変数ではありません。self.bar()

于 2013-02-27T12:16:33.087 に答える
2

私の推測では、解析の順序は (論理的な) 実行の順序とは異なります。特に、与えられた

array << error if (error = some_function)

次に、論理的には、実行は次のようになります

  1. 電話some_function
  2. 定義されていない場合errorは定義するerror
  3. の戻り値をsome_function代入error
  4. 評価if
  5. ifが に評価される場合、 の値をにtrue追加しますerrorarray

ただし、賢明な解析 (典型的な LR パーサーを想定) では、次のようになります。

  1. トークンarray(識別子) を取得しました。これは定義されていますか?はい。変数ですか?はい。
  2. トークン<<(オペレーター) を取得しました。arrayに応答し<<ますか? はい (それ以外の場合、「undefined method」エラーを出力します)。
  3. トークンerror(識別子) を取得しました。これは定義されていますか?いいえ。「未定義のローカル変数またはメソッド」を出力します。
于 2013-02-27T02:22:56.340 に答える