Operators vs. methods

Today I was just re-reading introductory Ruby docs as I prepare to teach
a few newbies tomorrow and I find myself feeling newbie-ish.

On ruby-lang.org's Ruby from other languagage highlights
http://www.ruby-lang.org/en/documentation/ruby-from-other-languages/
it points out that a method call is really a message to another object:

# This
1 + 2
# Is the same as this ...
1.+(2)
# Which is the same as this:
1.send "+", 2

That's all well and good, except that + isn't an ordinary method. If I
take another method like div:

# This
4.div(2)
# Is not the same as
4 div 2

In fact the latter is a syntax error.

When I first learned Ruby I was led to believe that + is just a method
with a funny name, but now that I think about it that cannot be. Not
only is there a special way that spaces are handled, but operator
precedence is pretty special too.

Where might I find this behavior documented? Is there a special list of
operators? How are they different from methods? Can I create my own?

Puzzled, or maybe I just need more sleep,

Sarah

···

--
Posted via http://www.ruby-forum.com/.

Sarah Allen wrote:

a method call is really a message to another object:

# This
1 + 2
# Is the same as this ...
1.+(2)
# Which is the same as this:
1.send "+", 2

That's all well and good, except that + isn't an ordinary method. If I
take another method like div:

# This
4.div(2)
# Is not the same as
4 div 2

In fact the latter is a syntax error.

When I first learned Ruby I was led to believe that + is just a method
with a funny name,

It is. As you've stated here:

# This
1 + 2
# Is the same as this ...
1.+(2)
# Which is the same as this:
1.send "+", 2

..and here is the proof:

class Fixnum
  def +(val)
    return "hello"
  end
end

puts 1 + 2
puts 1.send("+", 2)

--output:--
hello
hello

Ruby gives you a choice with some methods, like +() and =(), to use a
special syntax. Special syntaxes are commonly known as "syntactic
sugar". What happens is that the "sugared syntax" is converted into
the normal method call, so:

1 + 2 becomes 1.+(2)

and

obj.x = 10 becomes obj.x=(10) (where the method name is 'x=')

···

--
Posted via http://www.ruby-forum.com/\.

Seems your question has been answered already, but I couldn't resist jumping
in...

a method call is really a message to another object:

# This
1 + 2
# Is the same as this ...
1.+(2)
# Which is the same as this:
1.send "+", 2

# Which is the same as this, but more efficient:
1.send :+, 2

Any method you try to call will have its name converted into a symbol anyway,
so that is both slightly faster and slightly quicker to type. Probably doesn't
matter here, but I consider it good style.

# This
4.div(2)
# Is not the same as
4 div 2

That is true, and other people have already mentioned that it's syntactic
sugar. However, this isn't as much a limitation as you might think. As 4 is
not a method, I can't make the above work, but it's certainly possible to do
something like this:

foo div 2

Just look at rspec for some ideas... Probably not a beginner topic, though.

···

On Tuesday 25 August 2009 02:06:26 am Sarah Allen wrote:

Err, Hi Sarah,

Well i'm a newbie to fresh out of the womb in fact but i think i can point you in the right direction. Firstly yes operators are implemented as methods so 1+2 would be interpreted as 1.+(2) and since they are methods there behavoiur for classes that you create can be specified by you. Operators do also have a precedence as operators do in C and are methods of all objects of the Numeric Class.

From what I understand 'div' and '/' and not exactly the same. So 1/2 would be seen as 1./(2) whereas if you used 'div', you would write 1.div(2). The operator '/' seems to be equipt to deal with spaces but not 'div', that is probaly why you would use '()' to pass the argument. You also have 'fdiv' for floating point division and 'quo' returns a rational where possible.

This exact topic if covered in glorious technicolour in 'The Ruby Programming Language' by Flanagan and Matsumoto, but I am sure you can google it also.

Imran Nazir

Friend, Boho, House Owner, Citizen, Engineer

···

________________________________
From: Sarah Allen <sarah@ultrasaurus.com>
To: ruby-talk ML <ruby-talk@ruby-lang.org>
Sent: Tue, 25 August, 2009 8:06:26
Subject: operators vs. methods

Today I was just re-reading introductory Ruby docs as I prepare to teach
a few newbies tomorrow and I find myself feeling newbie-ish.

On ruby-lang.org's Ruby from other languagage highlights
http://www.ruby-lang.org/en/documentation/ruby-from-other-languages/
it points out that a method call is really a message to another object:

# This
1 + 2
# Is the same as this ...
1.+(2)
# Which is the same as this:
1.send "+", 2

That's all well and good, except that + isn't an ordinary method. If I
take another method like div:

# This
4.div(2)
# Is not the same as
4 div 2

In fact the latter is a syntax error.

When I first learned Ruby I was led to believe that + is just a method
with a funny name, but now that I think about it that cannot be. Not
only is there a special way that spaces are handled, but operator
precedence is pretty special too.

Where might I find this behavior documented? Is there a special list of
operators? How are they different from methods? Can I create my own?

Puzzled, or maybe I just need more sleep,

Sarah
--
Posted via http://www.ruby-forum.com/.

7stud -- wrote:

Ruby gives you a choice with some methods, like +() and =(), to use a
special syntax. Special syntaxes are commonly known as "syntactic
sugar". What happens is that the "sugared syntax" is converted into
the normal method call, so:

1 + 2 becomes 1.+(2)

and

obj.x = 10 becomes obj.x=(10) (where the method name is 'x=')

So, where might I find a list of the special sugary methods? and may I
define my own? I know I can override + and =, but could I make ß or foo
be sent to an object with syntax such as 4 foo 4 or "test"ß"this" ? (I
don't know that I would want to, but I am curious)

Thanks,
Sarah

···

--
Posted via http://www.ruby-forum.com/\.

7stud -- wrote:

Ruby gives you a choice with some methods, like +() and =(), to use a
special syntax.

Just to be clear, =() can't be used as a method name, you must add a
name ( x=() )
a.b = 2 calls the method "b=" of the object a : a.send("b=", 2)
a = 2 gives the name "a" to the object "2".

"a = 2" can't affect the old object names "a" (ruby != C++)

Sarah Allen wrote:

4 div 2

"4 div 2" means "4(div(2))"

note: The operators can't be used as variable names, so there is no risk
"var + 3" means "var(+, 3)", that is no valid ruby.

Just for fun:

I think it can be possible to create a dsl to do what you want:
- method_missing create objects (I will call them Flux)
  that keep its name and argument
- if the name of the method is also the name of an existing variable,
  and the argument is a Flux,
  then it call the stored method with variable and the stored argument
So "var div 2" means Flux.new(:div, 2).call(var) which means
"var.send(:div,2)"
But there are many limitations (for instance, "4" is not a valid method
name)

···

--
Etienne Vallette d'Osia
--
Posted via http://www.ruby-forum.com/\.

7stud -- wrote:

Ruby gives you a choice with some methods, like +() and =(), to use a
special syntax. Special syntaxes are commonly known as "syntactic
sugar". What happens is that the "sugared syntax" is converted into
the normal method call, so:

1 + 2 becomes 1.+(2)

and

obj.x = 10 becomes obj.x=(10) (where the method name is 'x=')

So, where might I find a list of the special sugary methods?

There is a list in the printed edition of the Pickaxe IIRC.

and may I
define my own? I know I can override + and =, but could I make ß or foo
be sent to an object with syntax such as 4 foo 4 or "test"ß"this" ? (I
don't know that I would want to, but I am curious)

You cannot as that would mean changing of the language's syntax.

Kind regards

robert

···

2009/8/25 Sarah Allen <sarah@ultrasaurus.com>:

--
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/

Sarah Allen wrote:

7stud -- wrote:

Ruby gives you a choice with some methods, like +() and =(), to use a
special syntax. Special syntaxes are commonly known as "syntactic
sugar". What happens is that the "sugared syntax" is converted into
the normal method call, so:

1 + 2 becomes 1.+(2)

and

obj.x = 10 becomes obj.x=(10) (where the method name is 'x=')

So, where might I find a list of the special sugary methods?

I don't know.

and may I
define my own?

Not that I'm aware of. However, you can define your own parser to
replace the sugared syntax with a method call:

r3test.rb

···

------
class Apple
  def shout(str)
    puts "#{str.upcase}!!!"
  end
end

a = Apple.new
a shout "hello" #<---'SUGARED' METHOD CALL
-----

----
class MyRubyParser
  attr_reader :data, :results

  def initialize(fname)
    @data = File.open(fname).readlines
    @results =
  end

  def desugar(meth_name)
    @data.each do |line|
      line = line.chomp
      result = line.gsub(/^(.+?) (#{meth_name}) (.+)$/, '\1.\2(\3)' )
      results << result
    end
  end
end

parser = MyRubyParser.new("r3test.rb")
parser.desugar("shout")

program = parser.results.join("\n")
eval(program)

--output:--
HELLO!!!

--
Posted via http://www.ruby-forum.com/\.

Robert Klemme wrote:

···

2009/8/25 Sarah Allen <sarah@ultrasaurus.com>:

obj.x = 10 becomes obj.x=(10) �(where the method name is 'x=')

So, where might I find a list of the special sugary methods?

There is a list in the printed edition of the Pickaxe IIRC.

Ah, yes. p. 339 (pickaxe2). The ones with check marks preceding them
in the operator table.

In order of precedence(highest at the top):

=
**
! ~ + - (unary plus and minus, e.g. -1)
* / %
+ -

<<

&
^ |
<= < > >=
<=> == === != =~ !~

--
Posted via http://www.ruby-forum.com/\.

7stud -- wrote:

So, where might I find a list of the special sugary methods?

There is a list in the printed edition of the Pickaxe IIRC.

Ah, yes. p. 339 (pickaxe2). The ones with check marks preceding them
in the operator table.

In order of precedence(highest at the top):

=
**
! ~ + - (unary plus and minus, e.g. -1)
* / %
+ -

<<

&
^ |
<= < > >=
<=> == === != =~ !~

Note that the majority of these call a method whose symbolic name is the
same as the operator itself, but there are some exceptions:

(1) unary plus and unary minus are :+@ and :-@

3.send(:-@)

=> -3

(2) !~ and != operators do not map directly to method calls, but call
:=~ and :== and negate the answers

class Foo; def ==(bar); puts "== #{bar}"; end; end

=> nil

Foo.new == "x"

== x
=> nil

Foo.new != "x"

== x
=> true

I have written programs which use x.send(:=, val). I call this smiley
programming :-@

···

--
Posted via http://www.ruby-forum.com/\.

Brian Candler wrote:

I have written programs which use x.send(:=, val). I call this smiley programming :-@

Why would you do that, though?

irb(main):001:0> class A
irb(main):002:1> def = index, value
irb(main):003:2> puts "Index: #{index} Value: #{value}"
irb(main):004:2> end
irb(main):005:1> end
=> nil
irb(main):006:0> A.new[1] = "hello"
Index: 1 Value: hello
=> "hello"

Is it because you only want to send a single value with no index?

-Justin

Brian Candler:

(2) !~ and != operators do not map directly to method
calls, but call :=~ and :== and negate the answers

>> class Foo; def ==(bar); puts "== #{bar}"; end; end
=> nil
>> Foo.new == "x"
== x
=> nil
>> Foo.new != "x"
== x
=> true

That is true in MRI 1.8, but not in MRI 1.9, where != can be
specified (but does fall back to a negated == if missing):

class Foo; def ==(bar); puts "== #{bar}"; end; end

=> nil

Foo.new == "x"

== x
=> nil

Foo.new != "x"

== x
=> true

class Foo; def !=(bar); puts "nooo, I’m not a negated ==!"; end; end

=> nil

Foo.new != 'x'

nooo, I’m not a negated ==!
=> nil

Foo.new == 'x'

== x
=> nil

— Shot

···

--
For some reason, this signature reminds everyone of Marvin Zelkowitz.

Justin Collins wrote:

Why would you do that, though?

There was a good reason why I needed to do send(:=, ...) but I can't
remember it off-hand. It may have been a variable-sized set of
arguments, or perhaps a private method.

···

--
Posted via http://www.ruby-forum.com/\.