横塚と申します。

これまでの一連の議論、興味深く拝見してます。
私もコンパイラ開発に携わっていたもので、「うん、うん、なるほど」と
思いながら読んでおり、実装上の都合も十分理解しているのですが・・・

ユーザの立場で言うと、未定義のまま参照されたらデフォルト値を返すよりも
素直に「未定義」エラーになってくれた方が嬉しいような気がしてきました。

数十行の使い捨てスクリプトを書くのなら良いのですが、数Ks以上のプログラムを
まじめに作ろうと思うと、それなりの作法が必要と思います。
作法には、変数には最初の参照前に初期値を代入するということも含みます。

自分でのデバッグや、ましてや数年後に他人が自分の書いたスクリプトを
エンハンスすることを想定すると、グローバル変数やインスタンス変数でも
定数と同じ挙動をしてくれるのが一番嬉しいかな。

実際にも、インスタンス変数をタイプミスしているのに、コンパイル時には
エラーとならず、実行時に変な動作をするので、やっと気付くということが
まま有ります。

私の感覚がおかしいのかな。
皆様、如何でしょう。


<20150117110728.EFC3.BF847F80 / nifty.com> の、
   "[ruby-list:50063] Re: x ||= 1" において、
   "take_tk <ggb03124 / nifty.com>"さんは書きました:

> たけ(tk)です
> 
> 言葉足らずにすみませんでした。
> 
> >   式1 が未定義もしくは偽のとき 式1 に 式2 の評価結果を代入し
> >  その値を全体の評価値とする。
> >  式1 が真のとき,その評価結果を全体の評価値とする。
> 
> 自己代入演算子は 式1 が未定義かどうかで区別しないということです。
> 
> >   式1 が偽のとき 式1 に 式2 の評価結果を代入し
> >  その値を全体の評価値とする。
> >  式1 が真のとき,その評価結果を全体の評価値とする。
> >  式1 が未定義の変数や定数、ハッシュなど場合には・・・と続く・・・
> 
> という感じでしょう。
> 
> ---
> 
> ローカル変数でエラーにならない理由と
> グローバル変数やインスタンス変数やハッシュでエラーにならない理由とは違い
> ます。
> 
> グローバル変数やインスタンス変数やハッシュでエラーにならない理由は、それ
> らが未定義のまま参照されてもデフォルト値 nil を返すからです。
> 
> irb(main):008:0> defined? @x  #=> nil ・・未定義でも
> irb(main):009:0> @x           #=> nil ・・デフォルト値で評価される。
> irb(main):010:0> @x &&= 1     #=> nil ・・デフォルト値で評価している。
> irb(main):011:0> @x           #=> nil
> irb(main):012:0> defined? @x  #=> nil ・・未定義のまま
> 
> irb(main):023:0> h = {}       #=> {}
> irb(main):024:0> h            #=> {}  ・・h[:x]が未定義でも
> irb(main):025:0> h[:x]        #=> nil ・・デフォルト値で評価される。
> irb(main):026:0> h[:x] &&= 1  #=> nil ・・デフォルト値で評価している。
> irb(main):027:0> h[:x]        #=> nil
> irb(main):028:0> h            #=> {}  ・・h[:x]は未定義のまま
> 
> それに対して、
> ローカル変数でエラーにならない理由は、ローカル変数が代入演算子の左辺に来
> たときには nil で初期化されるからです。
> 
> irb(main):002:0> defined? x   #=> nil
> irb(main):003:0> x            # NameError: undefined local variable or method
> irb(main):005:0> x &&= 1      #=> nil ・・代入演算子の左辺に来たので
> irb(main):006:0> x            #=> nil ・・nil で初期化されている。
> irb(main):007:0> defined? x   #=> "local-variable"
> 
> 定数でエラーになるのは、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
> 
> 

--
Daisuke Yokotsuka
yokots_d / c3-net.ne.jp