I just learned about Ruby's "spaceship operator", <=>
.
I find it interesting. Can Ruby define our own special operators like >=<
for opposite of <=>
?
Could it be applied to generic types like Java templates?
How do I do it?
There is a fixed set of operators in Ruby, some of which are syntactic sugar for message sends and can thus be overridden.
You can't add new operators. In Ruby, the fixed set of operators is part of the language syntax, and Ruby doesn't allow Ruby code to change the syntax of the language. If you want to add a new operator, you will have to convince matz to change the language specification, and you will have to convince the developers of Rubinius, JRuby, YARV, MagLev, and MRuby to implement this change.
These desugar into message sends and thus can be overridden by implementing the corresponding methods.
+foo
→ foo.+@()
, ergo: def +@; end
-foo
→ foo.-@()
, ergo: def -@; end
!foo
→ foo.!()
, ergo: def !; end
~foo
→ foo.~()
, ergo: def ~; end
foo + bar
→ foo.+(bar)
, ergo: def +(other) end
foo - bar
→ foo.-(bar)
, ergo: def -(other) end
foo * bar
→ foo.*(bar)
, ergo: def *(other) end
foo / bar
→ foo./(bar)
, ergo: def /(other) end
foo % bar
→ foo.%(bar)
, ergo: def %(other) end
foo ** bar
→ foo.**(bar)
, ergo: def **(other) end
foo >> bar
→ foo.>>(bar)
, ergo: def >>(other) end
foo << bar
→ foo.<<(bar)
, ergo: def <<(other) end
foo & bar
→ foo.&(bar)
, ergo: def &(other) end
foo ^ bar
→ foo.^(bar)
, ergo: def ^(other) end
foo | bar
→ foo.|(bar)
, ergo: def |(other) end
foo < bar
→ foo.<(bar)
, ergo: def <(other) end
foo > bar
→ foo.>(bar)
, ergo: def >(other) end
foo <= bar
→ foo.<=(bar)
, ergo: def <=(other) end
foo >= bar
→ foo.>=(bar)
, ergo: def >=(other) end
foo == bar
→ foo.==(bar)
, ergo: def ==(other) end
foo === bar
→ foo.===(bar)
, ergo: def ===(other) end
foo != bar
→ foo.!=(bar)
, ergo: def !=(other) end
foo =~ bar
→ foo.=~(bar)
, ergo: def =~(other) end
foo !~ bar
→ foo.!~(bar)
, ergo: def !~(other) end
foo <=> bar
→ foo.<=>(bar)
, ergo: def <=>(other) end
foo[bar, baz]
→ foo.[](bar, baz)
, ergo: def [](a, b) end
foo[bar, baz] = quux
→ foo.[]=(bar, baz, quux)
, ergo: def []=(a, b, c) end
foo.(bar, baz)
→ foo.call(bar, baz)
, ergo: def call(a, b) end
These don't desugar into message sends.
defined?
foo && bar
foo and bar
foo || bar
foo or bar
foo = bar
foo ||= bar
foo &&= bar
You can't override these independently, but they (at least partially) translate into other operators that can be overridden.
not foo
→ foo.!()
, ergo: def !; end
foo ω= bar
→ foo = foo ω bar
for any ω ∉ { ||
, &&
}