Operator Overloading

Let’s suppose I have a class like this one and then I create two
objects:

=-=-=-=-=-=-=-=-=-=-=-=
class Point

def initialize
x = 5
y = 10
z = 25
end

end

a = Point.new
b = Point.new
=-=-=-=-=-=-=-=-=-=-=-=

How do I do if I want to add a and b together to a new point called c?
Example:

c = a + b

How exactly should I implement the operator overloading feature? So that
x = 10, y = 20, z = 50. There are hardly any tutorial for this…

Thank you!

class Point
def +(other)
#there your code, i think
result = Point.new
result.x = self.x + other.x
result.y = self.y + other.y
result.z = self.z + other.z
return result
end
end

but you also need to make the variables accessable like
class Point
attr_accessor :x,:y,:z
end

and you should remove your init, it is wrong

On Tue, Oct 4, 2011 at 7:11 AM, Thescholar Thescholar
[email protected] wrote:

end
c = a + b

How exactly should I implement the operator overloading feature? So that
x = 10, y = 20, z = 50. There are hardly any tutorial for this…

Ruby doesn’t do operator overloading. But that doesn’t matter, since
“+” is a method. Thus:

class Point
def self.+(obj)
# Details of addition
end
end

Phillip G.

gplus.to/phgaw | twitter.com/phgaw

A method of solution is perfect if we can forsee from the start,
and even prove, that following that method we shall attain our aim.
– Leibniz

On Tue, Oct 4, 2011 at 12:11 AM, Thescholar Thescholar <
[email protected]> wrote:

end
c = a + b

How exactly should I implement the operator overloading feature? So that
x = 10, y = 20, z = 50. There are hardly any tutorial for this…

Thank you!


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

class Point
attr_accessor :x, :y, :z

def initialize(x=5, y=10, z=25)
self.x = x
self.y = y
self.z = z
end

def +(point)
Point.new x+point.x, y+point.y, z+point.z
end

def inspect
“(#{x}, #{y}, #{z})”
end
end

a = Point.new
b = Point.new

a # => (5, 10, 25)
b # => (5, 10, 25)
a + b # => (10, 20, 50)

On 10/04/2011 01:11 AM, Thescholar Thescholar wrote:

end
This won’t work since x, y and z in the above are local to the
constructor. So those variables will be lost when the constructor exits.

c = a + b

How exactly should I implement the operator overloading feature? So that
x = 10, y = 20, z = 50. There are hardly any tutorial for this…

Define a + method on your Point class:

def +(other)
self.x += other.x
self.y += other.y
self.z += other.z
self
end

That last line is IMPORTANT. Remember, Ruby methods treat the last value
evaluated in a method as the return value. So if you don’t put self in
then the return value for the + method will be the last addition.

So now with the above:

c = a + b

is the equivalent of doing:

c = a.+(b)

HTH.

On Tue, Oct 4, 2011 at 7:11 AM, Thescholar Thescholar
[email protected] wrote:

end
c = a + b

How exactly should I implement the operator overloading feature? So that
x = 10, y = 20, z = 50. There are hardly any tutorial for this…

Thank you!

For a full blown example you can look here:
http://blog.rubybestpractices.com/posts/rklemme/019-Complete_Numeric_Class.html

Kind regards

robert

Darryl Pierce wrote in post #1024950:

Define a + method on your Point class:

def +(other)
self.x += other.x
self.y += other.y
self.z += other.z
self
end

Warning!! That will mutate the point passed as the left-hand argument
of the ‘+’!

I would suggest instead:

def +(other)
Point.new(x+other.x, y+other.y, z+other.z)
end

(Of course, ‘x’ and ‘self.x’ are the same; you can write ‘self.x’ if you
think it’s clearer)

On 10/04/2011 10:03 AM, Brian C. wrote:

Warning!! That will mutate the point passed as the left-hand argument
of the ‘+’!

I would suggest instead:

def +(other)
Point.new(x+other.x, y+other.y, z+other.z)
end

DOH! Good point!

(Of course, ‘x’ and ‘self.x’ are the same; you can write ‘self.x’ if you
think it’s clearer)

I don’t think so. ‘x’ is a local variable, while ‘@x’ is an instance
variable. And since the fields are instance variables they have to be
prefixed with ‘@’.

On 10/04/2011 01:23 AM, Hans M. wrote:

but you also need to make the variables accessable like
class Point
attr_accessor :x,:y,:z
end

And add ‘@’ to them in the constructor.

On Tue, Oct 4, 2011 at 3:53 PM, Darryl L. Pierce [email protected]
wrote:

(Of course, ‘x’ and ‘self.x’ are the same; you can write ‘self.x’ if you
think it’s clearer)

I don’t think so. ‘x’ is a local variable, while ‘@x’ is an instance
variable. And since the fields are instance variables they have to be
prefixed with ‘@’.

Not quite. :slight_smile:

class Foo
attr_reader :x

def initialize(x)
@x = x
end

def bar
x # :slight_smile:
end
end

f = Foo.new(1)
puts f.bar

http://ideone.com/mbPc0

If there’s no local variable in the scope, the interpreter sees it as a
method call. If it’s ambiguous, it’ll pick the variable over the method
call, unless you force it with a trailing ().

x = 1
def x; 2; end
puts x
puts x()

My understanding (probly flawed) is
attr_reader :x

generates the following code:

def x
@x
end

so in bar that ‘x’ is a call to the x method, which returns the ‘@x
value
but doing it this way makes the x public readable, so should only be
used if that is needed
I’d stick with using @x

On 10/04/2011 11:11 AM, Adam P. wrote:

class Foo

def x; 2; end
puts x
puts x()

Okay, then this flies in the face of how I understood variables. I would
have thought the act of having ‘x’ in the definition for bar in the
above created a local variable in the current scope.

On Tue, Oct 4, 2011 at 5:31 PM, Darryl L. Pierce [email protected]
wrote:

end
x = 1
def x; 2; end
puts x
puts x()

Okay, then this flies in the face of how I understood variables. I would
have thought the act of having ‘x’ in the definition for bar in the
above created a local variable in the current scope.

Only an assignment creates a local variable in the scope.

def bar
x = 2
end

This creates a local variable x in the method bar. If there are no
assignments, the parser understands that references to x must be
method calls. This is due to the syntax ambiguity between methods and
local variables, because ruby allows you to call methods without
parens. So, to break the ambiguity, the parser marks references as
methods by default, and only as local variables when it sees an
assignment.

Jesus.

On Tue, Oct 4, 2011 at 10:03, Brian C. [email protected] wrote:

(Of course, ‘x’ and ‘self.x’ are the same; you can write ‘self.x’ if you
think it’s clearer)

Not quite. This is one of Ruby’s little gotchas. A naked “x” will be
taken as a local variable in the method. If you want to use an
instance variable you must precede it with either “self.” or “@”.

-Dave

On Tue, Oct 4, 2011 at 5:52 PM, Dave A.
[email protected] wrote:

On Tue, Oct 4, 2011 at 10:03, Brian C. [email protected] wrote:

(Of course, ‘x’ and ‘self.x’ are the same; you can write ‘self.x’ if you
think it’s clearer)

Not quite. This is one of Ruby’s little gotchas. A naked “x” will be
taken as a local variable in the method. If you want to use an
instance variable you must precede it with either “self.” or “@”.

The story is a bit more complex.

  1. writing

“x = exp” will always assign to a local variable. If you want to
invoke the setter method you must do “self.x = expr”.

  1. reading

“x” will access a local variable if it is defined and fall back to the
getter method if there is no variable. “self.x” will always invoke
the getter method regardless whether there is a local variable or not.

Example:

$ ruby19 -e ‘def x;1;end;public :x;def f;p x, self.x;x=99;p x,
self.x;end;f’
1
1
99
1

Needless to say that it’s not the best of practices to mix local
variables and properties of the same name. :slight_smile:

Kind regards

robert

On Tue, Oct 4, 2011 at 4:58 PM, Robert K.
[email protected]wrote:

“x” will access a local variable if it is defined and fall back to the
getter method if there is no variable. “self.x” will always invoke
the getter method regardless whether there is a local variable or not.

x() too, as an alternative to self.x. Although I prefer the latter.

Needless to say that it’s not the best of practices to mix local
variables and properties of the same name. :slight_smile:

+1!

On 10/04/2011 11:42 AM, Chris H. wrote:

but doing it this way makes the x public readable, so should only be
used if that is needed
I’d stick with using @x

AH! That’s what I missing, and what he meant by “the method”. Okay. The
OP though didn’t have the attr_accessor on the fields, though, that I
remember.

2011/10/4 Jesús Gabriel y Galán [email protected]:

Only an assignment creates a local variable in the scope.

This is actually only 1/7th true. There are as many as 7 ways to
introduce a new variable, out of which anybody would guess about 5 if
they though about it for a while ;), and 2 are quite obscure.

These are:

  1. Single- or multiple-assignment (including sub-assignment) anywhere
    an expression is allowed
  2. A for loop’s iterator variable(s)
  3. Formal arguments to a method
  4. Block arguments and block-local variables
  5. Stabby Lambda variables
  6. Rescue exception naming (rescue StandardError => err)
  7. Named Regexp captures in literal matches (/name: (?\w+)/ =~
    ‘name: Mike’ creates a local variable named “person” with value
    “Mike”)

(The above borrowed from GitHub - michaeledgar/ripper-plus: Parses Ruby code into an improved Ripper AST format)

Ah, the joys of high-level programming :smiley:

– Matma R.

On 10/04/2011 11:52 AM, Dave A. wrote:

On Tue, Oct 4, 2011 at 10:03, Brian C. [email protected] wrote:

(Of course, ‘x’ and ‘self.x’ are the same; you can write ‘self.x’ if you
think it’s clearer)

Not quite. This is one of Ruby’s little gotchas. A naked “x” will be
taken as a local variable in the method. If you want to use an
instance variable you must precede it with either “self.” or “@”.

Sorry, Brian was right. Try it out in the context of the code sample he
posted to see for yourself.

2011/10/4 Bartosz Dziewoński [email protected]:

  1. Single- or multiple-assignment (including sub-assignment) anywhere
    an expression is allowed
  2. A for loop’s iterator variable(s)

Kind of assignment :slight_smile:

  1. Formal arguments to a method

Good one, I was thinking only in the body of the method, but you can
also argue that someone does an assignment to them :slight_smile:

  1. Block arguments and block-local variables

Block arguments and block local variables are local to the block
scope, not the method.

  1. Stabby Lambda variables

What do you mean by this?

  1. Rescue exception naming (rescue StandardError => err)

Kind of assignment :slight_smile:

  1. Named Regexp captures in literal matches (/name: (?\w+)/ =~
    ‘name: Mike’ creates a local variable named “person” with value
    “Mike”)

Didn’t knew this one, thanks.

Jesus.