Skip to content

Instantly share code, notes, and snippets.

@janko

janko/script.rb

Last active Jan 25, 2019
Embed
What would you like to do?
Ruby operator coercion inconsistency
Value = Struct.new(:value) do
def coerce(other)
puts "called #{self}#coerce(#{other.inspect})"
[Value.new(other), self]
end
def +(other)
puts "called #{self} + #{other.inspect}"
end
def =~(other)
puts "called #{self} =~ #{other.inspect}"
end
def >=(other)
puts "called #{self} >= #{other.inspect}"
true
end
end
Value.new("foo") + Value.new("bar")
# >> called #<struct Value value="foo"> + #<struct Value value="bar">
Value.new("foo") + "bar"
# >> called #<struct Value value="foo"> + "bar"
"foo" + Value.new("bar")
# ~> TypeError: no implicit conversion of Value into String
1 + Value.new(2)
# >> called #<struct Value value=2>#coerce(1)
# >> called #<struct Value value=1> + #<struct Value value=2>
"foo" =~ Value.new("bar")
# >> called #<struct Value value="bar"> =~ "foo"
1 =~ Value.new(2)
# nothing called (nil is returned)
Value.new("foo") >= Value.new("bar") # => nil
# >> called #<struct Value value="foo"> >= #<struct Value value="bar">
"foo" >= Value.new("bar")
# ~> ArgumentError: comparison of String with Value failed
1 >= Value.new(2)
# >> called #<struct Value value=2>#coerce(1)
# >> called #<struct Value value=1> >= #<struct Value value=2>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.