Ruby

隊長!あまりフランクに使ってほしくなさげなメソッドを確認いたしました!

参考:知って得する!55のRubyのトリビアな記法

隊長!
あまりフランクに使ってほしくなさげなメソッドを確認いたしました!
ご報告になります!:cat::tiger::lion_face:

Numeric#coerce

数値のリストをn倍したらその要素がn倍されるようなNumListオブジェクトを定義

class NumList < Array
  def *(n)
    map { |e| e * n }
  end
end

NumList[1, 2, 3] * 3 # => [3, 6, 9]

もし、3 * NumList[1, 2, 3]でも処理できるようにしたい場合、
Numeric#coerceを使う。

class NumList < Array
  def *(n)
    map { |e| e * n }
  end

  def coerce(n)
    puts "#{self}<#{self.class}>" # [1, 2, 3]<NumList>
    puts "#{n}<#{n.class}>"       # 3<Fixnum>
    [self, n]
  end
end

NumList[1, 2, 3] * 3 # => [3, 6, 9]
3 * NumList[1, 2, 3] # => [3, 6, 9]

Fixnum#*は引数が型変換できないときはそのオブジェクトのcoerceメソッドを呼ぶので、そこに望む処理を書きます。

ちなみに :mouse:

3 * NumList[1, 2, 3]した時、selfnは以下のような値になっています。

〜省略〜
  def coerce(n)
    puts "#{self}<#{self.class}>" # [1, 2, 3]<NumList>
    puts "#{n}<#{n.class}>"       # 3<Fixnum>
    [self, n]
  end
〜省略〜

ちなみに:hamster:

Numeric#coerceでcoerceは定義されているので、Floatでもコードは変更せず同じような処理ができます。

class NumList < Array
  def *(n)
    map { |e| e * n }
  end

  def coerce(n)
    # 「3 * NumList[1, 2, 3]を実行で以下のような値になる。
    puts "#{self}<#{self.class}>" # [1, 2, 3]<NumList>
    puts "#{n}<#{n.class}>" # 1.5<Float>
    [self, n]
  end
end

1.5 * NumList[1, 2, 3] # => [1.5, 3.0, 4.5]

「あまりフランクに使ってほしくない」と言いましたが・・・:moyai:

バグが隠れてしまいそうなニオイを感じ、そう書きましたが、
もちろんケースバイケースだと思っております!:chicken::chicken::chicken: