0

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?

the Tin Man
  • 158,662
  • 42
  • 215
  • 303
user504909
  • 9,119
  • 12
  • 60
  • 109
  • 2
    Why would you *want* to define `>=<` to be "opposite"? I can see no usable reason for `>=<` that couldn't be easily defined using `-(a <=> b)` in a normal sort. See http://stackoverflow.com/questions/2642182/sorting-an-array-in-descending-order-in-ruby/2651028#2651028. Many of Ruby's operators are methods and can be defined/redefined, however be VERY careful when doing so. You can break a lot of code very fast when doing it carelessly. How to do it would be for your research as it's well documented how to define methods. – the Tin Man Nov 10 '15 at 00:37
  • @the Tin Man Yes, there is no reason to define >=<, just simple change the place of comparsion order, actually, I just want to know how to define generic operator in ruby. – user504909 Nov 10 '15 at 01:08
  • 1
    You can't define `>=<` without metaprogramming. The parser will raise exceptions. – Todd A. Jacobs Nov 10 '15 at 02:24

1 Answers1

3

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.

Overridable

These desugar into message sends and thus can be overridden by implementing the corresponding methods.

  • unary prefix
    • +foofoo.+@(), ergo: def +@; end
    • -foofoo.-@(), ergo: def -@; end
    • !foofoo.!(), ergo: def !; end
    • ~foofoo.~(), ergo: def ~; end
  • binary infix
    • foo + barfoo.+(bar), ergo: def +(other) end
    • foo - barfoo.-(bar), ergo: def -(other) end
    • foo * barfoo.*(bar), ergo: def *(other) end
    • foo / barfoo./(bar), ergo: def /(other) end
    • foo % barfoo.%(bar), ergo: def %(other) end
    • foo ** barfoo.**(bar), ergo: def **(other) end
    • foo >> barfoo.>>(bar), ergo: def >>(other) end
    • foo << barfoo.<<(bar), ergo: def <<(other) end
    • foo & barfoo.&(bar), ergo: def &(other) end
    • foo ^ barfoo.^(bar), ergo: def ^(other) end
    • foo | barfoo.|(bar), ergo: def |(other) end
    • foo < barfoo.<(bar), ergo: def <(other) end
    • foo > barfoo.>(bar), ergo: def >(other) end
    • foo <= barfoo.<=(bar), ergo: def <=(other) end
    • foo >= barfoo.>=(bar), ergo: def >=(other) end
    • foo == barfoo.==(bar), ergo: def ==(other) end
    • foo === barfoo.===(bar), ergo: def ===(other) end
    • foo != barfoo.!=(bar), ergo: def !=(other) end
    • foo =~ barfoo.=~(bar), ergo: def =~(other) end
    • foo !~ barfoo.!~(bar), ergo: def !~(other) end
    • foo <=> barfoo.<=>(bar), ergo: def <=>(other) end
  • n-ary "around-fix"
    • foo[bar, baz]foo.[](bar, baz), ergo: def [](a, b) end
    • foo[bar, baz] = quuxfoo.[]=(bar, baz, quux), ergo: def []=(a, b, c) end
    • foo.(bar, baz)foo.call(bar, baz), ergo: def call(a, b) end

Non-overridable

These don't desugar into message sends.

  • unary prefix
    • defined?
  • binary infix
    • foo && bar
    • foo and bar
    • foo || bar
    • foo or bar
    • foo = bar
  • compound assignment
    • foo ||= bar
    • foo &&= bar

Sort-of overridable

You can't override these independently, but they (at least partially) translate into other operators that can be overridden.

  • unary prefix
    • not foofoo.!(), ergo: def !; end
  • compound assignment
    • foo ω= barfoo = foo ω bar for any ω ∉ { ||, && }
Jörg W Mittag
  • 363,080
  • 75
  • 446
  • 653