ピッケル本を読む(6)第7章 式

メモ

p76

旧バージョンの Ruby では、属性設定メソッド(セッター?)によって返された値が代入の結果になりました。Ruby1.8 では、常に、引数の値が代入の値になります。つまり、属性設定メソッドの戻り値は破棄されます。

ということは、以下のコード中の return の値は破棄されてしまうってことだな。

class Test
  attr_reader :val
  def val=(val)
    @val = val
    return 99
  end
end

t = Test.new
# Ruby1.8 以前では、属性設定メソッドの戻り値が破棄されずに、a が 99 になる
a = t.val = 2
p a        #=>    2
p t.val    #=>    2

クラス内でアクセサを使う

これは本当に注意しないと見つけにくいバグを生み出しそうだ。

通常、クラス内のメソッドは同じクラスまたはスーパークラス内のメソッドを関数形式で(つまり self を暗黙のレシーバとして)呼び出すことができます。しかし、これは属性設定メソッドでは機能しません。Ruby はこのような代入文を見つけると、左辺に書かれた名前は属性書き込みメソッドの呼び出しではなく、ローカル変数であると判断します。

class BrokenAmplifier
  attr_accessor :left_channel, :right_channel
  def volume=(vol)
    # left_channel に self を付けるの忘れている!
    # これでは left_channel はメソッド volume= のローカル変数として扱われてしまう
    left_channel = self.right_channel = vol
  end
end

ba = BrokenAmplifier.new
ba.left_channel = ba.right_channel = 99
ba.volume = 5
p ba.left_channel     #=>    99
p ba.right_channel    #=>    5


今日はここまで。
再開(2007年10月12日(金))


nil でも false でも無い値はすべて真。
論理式は、最後に評価された値を返す。以下はその例。

>> nil and true
=> nil
>> false and true
=> false
>> 99 and false
=> false
>> 99 and nil
=> nil
>> 99 and "cat"
=> "cat"


出た、初期化イディオム。もっと早く知りたかったな。

p80

words = {}
(words["key"] ||= []) << "word"


今日はここまで。p84 まで読んだ。最近ほんとに読んでないけど、気にしない。続けることが大事と言い訳してみる。