3

What is wrong with this?

class Vec2
  attr_accessor :x, :y
  # ...
  def += (v)
    @x += v.x
    @y += v.y
    return self
  end
  # ...
end

I've not been able to find much online. Someone said it is because += in ruby is done calling + and then =, he was kidding right?

In the amusing case he was right, is there some workaround (aside from defining a method called "add")?

0

2 Answers 2

6

Someone said it is because += in ruby is done calling + and then =, he was kidding right?

No, he is right (except that "calling =" is a bit inaccurate as = is not a method).

is there some workaround (aside from defining a method called "add")?

You mean other than defining + and living with the fact that += will change the variable and not the object?

You could change + to mutate the object and then return self, in which case v1 += v2 would be the same as v1 + v2 and would mutate the object. However I'd strongly advise against that as no one would expect + to be mutating (similarly most ruby-literate people would expect += to reassign the variable and not mutate the object, so trying to change that might just be inadvisable altogether).

Other than that, no, there's no way to work around this.

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks, i will accept this since it address the work around part too.
+1 for "However I'd strongly advise against that as no one would expect + to be mutating (similarly most ruby-literate people would expect += to reassign the variable and not mutate the object, so trying to change that might just be inadvisable altogether)." - nothing like setting up a booby-trap for the unexpecting. People went hog-wild overloading C++ operators, and I remember having to search out what they heck they'd done to know if an operator had new "features".
4

He was right. += is a language construct of sorts, that sets the variable reference equal to the result of the implied + operation. += can never actually be a method and behave as expected:

a = [1, 2, 3]
b = a
b << 4
b += [5, 6, 7]
p a # => [1, 2, 3, 4]
p b # => [1, 2, 3, 4, 5, 6, 7]

a and b here both contain references to the same object, which is why running << to add an element to b also affects a. As we can see, however, += isn't supposed to modify the object itself; it's supposed to change what's being stored in that variable, which is why the value of a is here untouched.

It really is exactly equivalent to the longhand.

b = a + [5, 6, 7]

Written that way, you expect a new array to be formed, and for a to remain the same. += is shorthand for exactly that, so does not mutate a in any way.

You can always define your own + to return a fresh vector.

def +(v)
  new_vector = self.class.new
  new_vector.x = @x + v.x
  new_vector.y = @y + v.y
  new_vector
end

4 Comments

Actually i would expect exactly that, i.e. that += modify the object referenced by the variable, not the content of the variable, but i guess that is just me. Thanks for the answer anyway :)
By the way, in the code it was @x += v.x; @y += v.y, because new_vector.x = @x + v, new_vector.y = @y + v doesn't make sense
@nespola: …>_<. Just woke up. These are actually vectors being added. Get it now xD Edited appropriately.
@nespola If += modified the object referenced by the variable, then a = 41; a+=1 would cause all integer values of 41 in your runtime to suddenly become 42.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.