[ruby-list:50059] Re: x ||= 1
From:
take_tk <ggb03124@...>
Date:
2015-01-15 08:27:01 UTC
List:
ruby-list #50059
たけ(tk)です > 式1 ||= 式2 > は > 式1 = 式1 || 式2 > でもなく・・・ (1) 「式1 ||= 式2」は「式1 = 式1 || 式2」のシンタックスシュガーであ る。動作においては同等であるように設計されている。 (2) 式1がローカル変数であり、かつ、未定義のとき、ローカル変数が代入 文の左辺に来た段階(「x =」を発見した段階で)nil で初期化し、その後に右 辺を評価する。従って、「x ||= 1」も「x = ( x || 1 )」も未定義エラーにな らない。 (2−2)式1がグローバル変数やインスタンス変数である場合には、未定義だ と nil の扱いになるので、未定義エラーにはならなずに、代入される。 (2−3)式1が定数であり、かつ、未定義のときには nil での初期化は行われ ないので、未定義エラーになる。 (3) 「x ||= 1」や「x = ( x || 1 )」で x が真であるとき、 「x = ( x || 1 )」では「x = x」という無駄な代入が実行されることになるが、 「x ||= 1」の場合は無駄な代入は省略され、何もしないように内部的に最適化 されている。 (4)代入が行われないという意味では「x || ( x = 1)」に似ている。しかし、 最初の式1がローカル変数 x で未定義のとき、「x || ( x = 1)」では x が代入 文の左辺ではないので、未定義エラーになる。それに対して、「x ||= 1」も 「x = ( x || 1 )」も未定義エラーにならないので、、 「x ||= 1」が「x || ( x = 1)」と同等であるとは言えない。 (4−2)なお、グローバル変数やインスタンス変数の場合は、未定義であって も、「$x || ( $x = 1 )」はエラーにならない。 (5) (3)(4)は内部的な最適化による動作の省略の話なので、文法的に は、(1)(2)のみの説明に留めるのが正しい。せいぜい(3)までの説明に するべき。従って、 http://docs.ruby-lang.org/ja/2.2.0/doc/spec=2foperator.html#selfassign が書きすぎである。 ということではないでしょうか? ---- グローバル変数やローカル変数は未定義だと nil と評価される。 irb(main):001:0> x NameError: undefined local variable or method `x' for main:Object irb(main):002:0> $x => nil irb(main):003:0> X NameError: uninitialized constant X 定数では左辺に来ても nil で初期化されない。 irb(main):004:0> x ||= 1 => 1 irb(main):005:0> $x ||= 1 => 1 irb(main):006:0> X ||= 1 NameError: uninitialized constant X グローバル変数やインスタンス変数なら「$x || ( $x = 1 )」はエラーにならな い。 irb(main):012:0> defined? $x => nil irb(main):013:0> $x || ( $x = 1 ) => 1 irb(main):014:0> defined? $x => "global-variable" irb(main):015:0> irb(main):015:0> defined? @x => nil irb(main):016:0> @x || ( @x = 1 ) => 1 irb(main):017:0> defined? @x => "instance-variable" irb(main):018:0>