Operator overloading

Hi,

With Ruby operaotr overloading is simply done by a definition like

  class foo
		...

		def +( other )
			# some code
		end

		...
  end 

I thought I did something very clever :wink: by defining also:

  class foo
		...

		def +=( other )
			# some code
		end

		...
  end 

but Ruby wasn’t impressed and gave me a SYNTAX ERROR instead on the
first opening “(”.

Is it possible to overload operators like += -= &&= and such ?

And how can I do this ?

Kind regards and have a nice weekend,
Meino

Is it possible to overload operators like += -= &&= and such ?

+= is not an operator.

a += 1

is just a shortcut for

a = a + 1

Guy Decoux

Hi,

I’m pretty new to Ruby, so someone may step in quickly to correct me. But
my understanding is that, for any of the standard dyadic operators (+, -,
etc.) the shorthand

j += 1

is expanded before evaluation to:

j = j + 1

I’ve experimented with a couple of overloads of the ‘+’ operator, and I
always got exactly what I expected from ‘+=’ for free…Principle of Least
Surprise, indeed :slight_smile:

  • dan

“Meino Christian Cramer” Meino.Cramer@gmx.de wrote in message
news:20030921.143434.92569875.Meino.Cramer@gmx.de

···

Is it possible to overload operators like += -= &&= and such ?

And how can I do this ?

Kind regards and have a nice weekend,
Meino

“Meino Christian Cramer” Meino.Cramer@gmx.de schrieb im Newsbeitrag
news:20030921.143434.92569875.Meino.Cramer@gmx.de

Is it possible to overload operators like += -= &&= and such ?

And how can I do this ?

You can’t. And you don’t need to. As others pointed out already, Ruby
treats all the assignment arithmetic operators as shortcuts and invokes
the appropriate operator. So

foo (op)= bar <=> foo = foo (op) bar

Where (op) is pretty much every operator you’d like to put there.
Implementing Foo#+ gives you Foo+= automatically.

Regards

robert

Not quite - I think j += 1 only evaluates j once. I recall one instance
where that helped me, performance-wise.

···

On Sun, 21 Sep 2003 11:29:27 -0700, dhtapp wrote:

Hi,

I’m pretty new to Ruby, so someone may step in quickly to correct me. But
my understanding is that, for any of the standard dyadic operators (+, -,
etc.) the shorthand

j += 1

is expanded before evaluation to:

j = j + 1


Tom Felker, tcfelker@mtco.com
http://vlevel.sourceforge.net - Stop fiddling with the volume knob.

How long do we want to live in a world where profit is made by forcing the
competition to reinvent the wheel?

“Robert Klemme” bob.news@gmx.net wrote in message news:bkmq5r$3dhd5$2@ID-52924.news.uni-berlin.de

You can’t. And you don’t need to. As others pointed out already, Ruby
treats all the assignment arithmetic operators as shortcuts and invokes
the appropriate operator. So

Er. “You don’t need to” is rather extreme. What about numerical cases?

i.e., if m is a large matrix, then “m += 1” and “m = m + 1” are rather
different beasts, since the “obvioius” interpretation of the first involves
simply incrementing the matrix in place, while the second involves a
copy.

Is there a standard work-around for this? This was one of the reasons I
stuck with python over ruby, but I’ve got to admit that I didn’t spend a
huge amount of time researching.

Thanks for any info,

-Johann

Hi –

Hi,

I’m pretty new to Ruby, so someone may step in quickly to correct me. But
my understanding is that, for any of the standard dyadic operators (+, -,
etc.) the shorthand

j += 1

is expanded before evaluation to:

j = j + 1

Not quite - I think j += 1 only evaluates j once. I recall one instance
where that helped me, performance-wise.

The j on the left isn’t being evaluated; it’s just being assigned to.
So in cases with objects that can have more than one instance (like
String), you get a new object:

irb(main):001:0> j = “abc”
=> “abc”
irb(main):002:0> j.id
=> 537889088
irb(main):003:0> j += “d”
=> “abcd”
irb(main):004:0> j.id
=> 537881918

With integers you don’t, of course, but it’s also a case of assigning
to a variable, where the variable name on the left just serves to
accept the assignment (in the expanded form).

David

···

On Mon, 22 Sep 2003, Tom Felker wrote:

On Sun, 21 Sep 2003 11:29:27 -0700, dhtapp wrote:


David Alan Black
home: dblack@superlink.net
work: blackdav@shu.edu
Web: http://pirate.shu.edu/~blackdav

Really? I would say that the second means the same as the first,
because that’s the way it works everywhere else in Ruby.

Maybe Matz has programmed my brain for the first to be the same as
the second.

···

Johann Hibschman (jhibschman@yahoo.com) wrote:

i.e., if m is a large matrix, then “m += 1” and “m = m + 1” are rather
different beasts, since the “obvioius” interpretation of the first involves
simply incrementing the matrix in place, while the second involves a
copy.


Eric Hodel - drbrain@segment7.net - http://segment7.net
All messages signed with fingerprint:
FEC2 57F1 D465 EB15 5D6E 7C11 332A 551C 796C 9F04

Johann Hibschman wrote:

“Robert Klemme” bob.news@gmx.net wrote in message news:bkmq5r$3dhd5$2@ID-52924.news.uni-berlin.de

You can’t. And you don’t need to. As others pointed out already, Ruby
treats all the assignment arithmetic operators as shortcuts and invokes
the appropriate operator. So

Er. “You don’t need to” is rather extreme. What about numerical cases?

i.e., if m is a large matrix, then “m += 1” and “m = m + 1” are rather
different beasts, since the “obvioius” interpretation of the first involves
simply incrementing the matrix in place, while the second involves a
copy.

Is there a standard work-around for this? This was one of the reasons I
stuck with python over ruby, but I’ve got to admit that I didn’t spend a
huge amount of time researching.

narray has

 self.add! other
 self.sbt! other
 self.mul! other
 self.div! other
 self.mod! other

which presumably are in-place ops. Anyway, they are faster than *= and
friends:

                         user     system      total        real

warmup 16.980000 2.850000 19.830000 ( 22.501646)
using *= and /= 0.400000 0.050000 0.450000 ( 0.462865)
using mul! and div! 0.160000 0.020000 0.180000 ( 0.181544)
using no ops 0.000000 0.000000 0.000000 ( 0.006473)

(on PIII850).

···

=================================
require ‘narray’
require ‘benchmark’

Benchmark.bm(22) do |test|

reps = 10_000

m = NMatrix.float(100,100).fill(1)

test.report(“warmup”) do
(1…reps).each do |i|
m *= i
m /= i
end
end

m = NMatrix.float(3,3).fill(1)

test.report(“using *= and /=”) do
(1…reps).each do |i|
m *= i
m /= i
end
end

m = NMatrix.float(3,3).fill(1)

test.report(“using mul! and div!”) do
(1…reps).each do |i|
m.mul! i
m.div! i
end
end

m = NMatrix.float(3,3).fill(1)

test.report(“using no ops”) do
(1…reps).each do |i|
end
end

end

“Johann Hibschman” jhibschman@yahoo.com schrieb im Newsbeitrag
news:41b772c.0309221105.26d32b4f@posting.google.com

“Robert Klemme” bob.news@gmx.net wrote in message
news:bkmq5r$3dhd5$2@ID-52924.news.uni-berlin.de

You can’t. And you don’t need to. As others pointed out already,
Ruby
treats all the assignment arithmetic operators as shortcuts and
invokes
the appropriate operator. So

Er. “You don’t need to” is rather extreme. What about numerical cases?

i.e., if m is a large matrix, then “m += 1” and “m = m + 1” are rather
different beasts, since the “obvioius” interpretation of the first
involves
simply incrementing the matrix in place, while the second involves a
copy.

Is there a standard work-around for this?

Resort to methods with proper names (like “add!”, “mult!” etc. Convention
is, that an exclamation mark denotes methods that modify the receiver).

Personally I feel very comfortable with Ruby not encouraging overloading
operators all the time as C++ does. Readability doesn’t always benefit
from overloading. And there is nothing that can’t be achieved with a
method call (from a functional perspective).

Regards

robert

j += 1

is expanded before evaluation to:

j = j + 1

Not quite - I think j += 1 only evaluates j once. I recall one instance
where that helped me, performance-wise.

The j on the left isn’t being evaluated; it’s just being assigned to.
So in cases with objects that can have more than one instance (like
String), you get a new object:

He is referring to this case:

def counter
c=0
return proc { c+=1 }
end

cc = counter

a = [ “a”, “b”, “c” ]
a[cc.call] += “x” # only one cc.call evaluated, only a[1] changed
a # [ “a”, “bx”, “c” ]

cc = counter
a = [ “a”, “b”, “c” ]
a[cc.call] = a[cc.call] + “x” # a[1] = a[2] + “x”
a # [ “a”, “cx”, “c” ]

Joel VanderWerf wrote:

                        user     system      total        real

warmup 16.980000 2.850000 19.830000 ( 22.501646)
using *= and /= 0.400000 0.050000 0.450000 ( 0.462865)
using mul! and div! 0.160000 0.020000 0.180000 ( 0.181544)
using no ops 0.000000 0.000000 0.000000 ( 0.006473)

Oops. I meant for all arrays to be 100x100, in which case the times are
more reasonable:

                         user     system      total        real

warmup 16.900000 2.740000 19.640000 ( 22.567519)
using *= and /= 16.650000 2.820000 19.470000 ( 22.195233)
using mul! and div! 5.360000 0.440000 5.800000 ( 6.051514)
using no ops 0.010000 0.000000 0.010000 ( 0.006231)

But there is still a factor of 3 improvement in mul! and div! over *=
and /=.