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
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

Sarah A. 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=’)

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

2009/8/25 Sarah A. [email protected]:

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

Sarah A. 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!!!

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 A. 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

Robert K. wrote:

2009/8/25 Sarah A. [email protected]:

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)

  • / %

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

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 :-@

Seems your question has been answered already, but I couldn’t resist
jumping
in…

On Tuesday 25 August 2009 02:06:26 am Sarah A. 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

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.

Brian C. 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

Justin C. 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.

Brian C.:

(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

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 A. [email protected]
To: ruby-talk ML [email protected]
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
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