5.5 です。

On 15/01/17 11:07, take_tk wrote:
> たけ(tk)です
> 
> 言葉足らずにすみませんでした。
> 
>>    式1 が未定義もしくは偽のとき 式1 に 式2 の評価結果を代入し
>>  その値を全体の評価値とする。
>>  式1 が真のとき,その評価結果を全体の評価値とする。
> 
> 自己代入演算子は 式1 が未定義かどうかで区別しないということです。
> 
>>    式1 が偽のとき 式1 に 式2 の評価結果を代入し
>>  その値を全体の評価値とする。
>>  式1 が真のとき,その評価結果を全体の評価値とする。
>>  式1 が未定義の変数や定数、ハッシュなど場合には・・・と続く・・・
> 
> という感じでしょう。

そうですね,真偽と未定義は分けて考えないといけないということ
ですね。

> ローカル変数でエラーにならない理由と
> グローバル変数やインスタンス変数やハッシュでエラーにならない理由とは違い
> ます。
> 
> グローバル変数やインスタンス変数やハッシュでエラーにならない理由は、それ
> らが未定義のまま参照されてもデフォルト値 nil を返すからです。


> それに対して、
> ローカル変数でエラーにならない理由は、ローカル変数が代入演算子の左辺に来
> たときには nil で初期化されるからです。

そうですね。


> 定数でエラーになるのは、nil で初期化されることもなく、デフォルト値も返さ
> ないので、参照の段階でエラーになるからです。
> 
> irb(main):013:0> defined? X   #=> nil
> irb(main):014:0> X            # NameError: uninitialized constant X
> irb(main):015:0> X &&= 1      # NameError: uninitialized constant X
> irb(main):016:0> X            # NameError: uninitialized constant X
> irb(main):017:0> defined? X   #=> nil

んー,でもまだちょっと分からない点があります。

X &&= 1 は NameError になるのに,X ||= 1 はならないことです。

それぞれの構文木は

  s(:op_asgn_and, s(:const, :X), s(:cdecl, :X, s(:lit, 1)))

  s(:op_asgn_or, s(:const, :X), s(:cdecl, :X, s(:lit, 1)))

で,違っているのは :op_asgn_and か :op_asgn_or かだけです。

どちらの場合も,実行の段にはまず s(:const, :X) の部分,つまり
定数 X の参照を行うのだと思うんですが,何が違うんでしょうね。

※ちなみに Ruby 1.8.7 ではどちらも NameError になりました。
Ruby 1.9 で何かが変わったんですね。

-- 
5.5 / moji.gr.jp