0

この質問は特にRuby 1.9.3を扱います:

p defined?(a)
p binding.eval "defined?(a)"
b = lambda { |x| x }
p b.binding.eval "defined?(a)" # This prints "local-variable"
p defined?(a) # This prints nil!
a = 2
p defined?(a)
p b.binding.eval "defined?(a)"

私を混乱させるのは4行目です。これが nil ではなく「local-variable」を出力する理由がわかりません。これは、ラムダがどういうわけか「遠くを見ている」ことを暗示しているようです。(defined?オペレーターであることはこれと関係があると思います。)

また、バインディングは定義されていると言っていますが、次のように使用しようとしています:

p b.binding.eval "a"

6 行目の割り当ての前に NameError が発生します。

編集:これをテストしました

  • 1.9.3-362
  • 1.9.3-374
  • 2.0.0-プレビュー2

すべてのケースで同じ動作が得られます。

4

3 に答える 3

2

何が起こるかというとdefined?、解析時に呼び出すだけで、変数aがまだ存在しないため、期待どおりに返さnilれます。ただし、eval呼び出すdefined?と、実行時に延期されます。しかしdefined?、まだレキシカルスコープであり、ファイル全体がすでに解析およびコンパイルされているため、変数a 存在します。これは、解析時に作成されたものであり、これで完了です。

これを簡単な例で示します。

defined? a         #=> nil
eval 'defined? a'  #=> "local-variable"
a = 2
defined? a         #=> "local-variable"

しかし、まったく定義aしない場合:

defined? a         #=> nil
eval 'defined? a'  #=> nil

ご覧のとおり、これは とは何の関係もありません。binding代わりに、ファイル全体が解析された後までevalの評価を延期することに関係しています。defined?

于 2013-02-08T01:23:10.937 に答える
0

Rubyソースパーサーの機能です。Ruby ソース コードに変数の割り当てが存在する場合、プログラムの実行中に呼び出されなくても、nil に初期化されます (したがって、定義されます)。6 行目にローカル変数a ( a = 2) への代入があります。ソースが実行される前に ruby​​ パーサーによって nil に初期化されるため、3 行目の割り当てのに定義されていても問題ありません。ラムダは新しいスコープを導入しないため変数について認識しているため、当然のことながら「ローカル変数」の結果 (a == nil) が得られます。詳細については、この回答を参照してください。

irb で実行する場合と Ruby インタープリターに渡す場合の動作の違いは、上記の段落に直接関係しています。irb は式を 1 行ずつ (REPL) 評価し、ruby は実行前にソース全体を解析します。

于 2013-02-08T00:53:46.927 に答える
0

謎の元になっているのは、実は 6 行目です。コードが実行されていない場合でも、Ruby は条件内にオブジェクトを作成します。変数が割り当てられている場合は、暗黙的に宣言されます。 このブログ投稿には簡単な説明があります

これは自分でもちょっと意外でした。コードに関しては、新しい IRB セッションでは、4 行目の出力として 'nil' が表示されるはずですが、コードを複数回実行すると、変数は (Nil オブジェクトの形式で) 既にそこにあり、ローカル変数が存在するという厄介なニュースを取得します。YMMV。

于 2013-02-07T22:37:33.500 に答える