quattro_4 scribble

scribble 落書き (調べた事をただ落書きする)

RubyTapas #205 - #210

205 Comparable

  • identity, equivalence
    • case equality
    • and hash equality
  • comparison operator
    • >, ==, <
    • spaceship operator
      • <=>
      • .sort
  • include Comparable
    • >, ==, <不要

206 Coercion

  • arithmetic operations
    • +, -, *, /

順番変えるとエラー

Feet.new(50) * 23               # => #<Feet:1150.0>

23 * Feet.new(50)              # => 
# ~> -:3:in `*': Feet can't be coerced into Fixnum (TypeError)
# ~>    from -:3:in `<main>'

Rational.coerce

Rational(2, 3).coerce(10)           # => [(10/1), (2/3)]
Rational(10, 1) * Rational(2, 3)    # => (20/3)
10 * Rational(2, 3)                 # => (20/3)
  def coerce(other)
    unless other.is_a?(Numeric)
      raise TypeError, "Can't coerce #{other}" 
    end
    [Feet.new(other), self]
  end

207 Conversion Function

★★

conversion method returns 0, whereas the function raises an error

"ham sandwich".to_i             # => 0
Integer("ham sandwich")         # => 
# ~> -:2:in `Integer': invalid value for Integer(): "ham sandwich" (ArgumentError)
# ~>    from -:2:in `<main>'

nil.to_i                        # => 0
Integer(nil)                    # => 
# ~> -:2:in `Integer': can't convert nil into Integer (TypeError)
# ~>    from -:2:in `<main>'

conversion function

def Feet(value)
  case value
  when Feet then value
  else
    value = Float(value)
    Feet.new(value)
  end
end
module Quantities
  class Feet
    # ...
  end

...

  module_function :Feet
end

include Quantities
Feet(1234)
# or:
Quantities.Feet(1234)

208 Lenient Conversions

  • #to_i are conventionally
    • lenient 情け深い、大目に見る
  • #to_f is idiomatic to mean "please try your best to give me a Float, but don't worry about it if you can't"

strict conversion, lenient explicit conversion

The lenient conversion methods are particularly useful when we are dealing with messy data and a few extra zeroes won't hurt anything.

The strict conversion functions, on the other hand, are a great way to "fail fast" when bad data finds its way into a critical method.

209 Explicit Conversion

class Feet
  # ...
  alias_method :to_f, :magnitude

  def to_i
    to_f.to_i
  end

210 Implicit Conversion

Month = Struct.new(:name, :index) do
  def to_s
    name
  end

  def to_i
    index
  end
  alias_method :to_int, :to_i
end
  • #to_int
    • if it responds to the #to_int message, Ruby will send it the #to_int
  • interchangeably 区別しない、同じ意味で

Ruby supports the idea of both explicit and implicit conversion methods

However, this is a technique that should be used sparingly and with careful consideration