Skip to content

Instantly share code, notes, and snippets.

@janko
Last active January 25, 2019 00:50
Show Gist options
  • Save janko/fcd843fa2e1743b0ad10500e4094d2ba to your computer and use it in GitHub Desktop.
Save janko/fcd843fa2e1743b0ad10500e4094d2ba to your computer and use it in GitHub Desktop.
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