$30 off During Our Annual Pro Sale. View Details »

Coercion in Ruby

Coercion in Ruby

Grzegorz Witek

May 09, 2018
Tweet

More Decks by Grzegorz Witek

Other Decks in Technology

Transcript

  1. Coercion in Ruby
    Between the strong and weak typing

    View Slide

  2. Grzegorz Witek

    View Slide

  3. Strong vs. weak typing
    $> 3 + “a”
    Python: unsupported operand type(s) for +: 'int' and 'str'
    Ruby: String can't be coerced into Fixnum
    Javascript: “3a”

    View Slide

  4. Strong vs. weak typing
    $> 3 + “a”
    Python: unsupported operand type(s) for +: 'int' and 'str'
    Ruby: String can't be coerced into Fixnum
    Javascript: “3a”

    View Slide

  5. Coercion in Ruby
    class Money < Struct.new(:amount)
    def *(value)

    amount * value

    end
    end

    View Slide

  6. How do I Ruby?
    money = Money.new(3)
    money * 2 # => 6
    2 * money # => ERROR U FAIL

    View Slide

  7. Bad solution
    class Fixnum

    alias :old_multiply :*
    def *(val)

    if defined?(Money) && val.is_a?(Money)

    return self * val.amount

    else

    old_multiply(val)

    end

    end

    end

    View Slide

  8. Bad solution
    Pros: works
    Cons: it’s wrong on as many levels as you can imagine


    View Slide

  9. Good solution
    class Money < Struct.new(:amount)


    def *(value)

    amount * value

    end
    def coerce(other) 

    [self, other]

    end
    end

    View Slide

  10. Good solution
    def coerce(other) 

    [self, other]

    end

    View Slide

  11. Good solution
    def coerce(other) 

    [other, amount]

    end

    View Slide

  12. How does it work?
    Short answer:
    when Ruby can’t handle the param type, it calls
    arg.coerce(self)
    it gets 2 elements array, and calls array[0].method(array[1])

    View Slide

  13. How does it work?
    Fixnum#*(Money) => omg, what to do?

    View Slide

  14. How does it work?
    Fixnum#(Money)* => omg, what to do?
    Money#coerce => [Money, Fixnum]

    View Slide

  15. How does it work?
    Fixnum#*(Money) => omg, what to do?
    Money#coerce => [Money, Fixnum]
    Money#*(Fixnum) => I know how to handle it!

    View Slide

  16. Coercion in Ruby
    Thanks!
    Grzegorz Witek

    @arnvald

    View Slide