Things That Newcomers to Ruby Should Know (10/16/02)

But why does it really, REALLY mean that? Was there a reason for doing
this? Is it non-trivial to have ‘+=’ mean ‘append()’?

Drew

···

-----Original Message-----
From: Hal E. Fulton [mailto:hal9000@hypermetrics.com]
Sent: Monday, October 21, 2002 11:18 PM
To: ruby-talk@ruby-lang.org
Subject: Re: Things That Newcomers to Ruby Should Know (10/16/02)

It’s a feature. :slight_smile: The notation a+=b really, REALLY
means a = a + b. There is a + operator, but never a
+= operator, in Ruby (or any other assignment).

Hal

But why does it really, REALLY mean that? Was there a reason for doing
this? Is it non-trivial to have ‘+=’ mean ‘append()’?

Drew

It’s just the way it is. In C++, the following are separate overloadable
operators: =, +, and +=. In Ruby, = is not overloadable, + is, and += is not
even an operator.

I think Ruby’s way makes sense. In C++ it is possible for + and += to be
semantically incompatible. Or for + to be valid and not +=.

If performance is what you’re worried about, inlining += is not the place to
start.

Cheers,
Gavin

···

From: “Mills Thomas (app1tam)” app1tam@ups.com

From: Hal E. Fulton [mailto:hal9000@hypermetrics.com]

It’s a feature. :slight_smile: The notation a+=b really, REALLY
means a = a + b. There is a + operator, but never a
+= operator, in Ruby (or any other assignment).

Hal

Hi,

As already been pointed out, this is because in Ruby when a variable is
assigned to another variable, the new variable simply refers to the same
object that the old variable refers to:

a = AnObject.new
b = a    # b really refers to the same, identical AnObject as a

Therefore, if ‘+=’ means ‘append()’, then what you will have is

b += anotherObj    # a will also be a = a.append(anotherObj)

The only safe/natural way of having ‘+=’ to mean ‘append()’ is by changing
the semantic in Ruby by having the variable assignment operator to invoke
some copy method:

# Not a Ruby code
a = AnObject.new
b = a    # b = a.copy()
b += anotherObj    # b = b.append(anotherObj), a unchanged

But Ruby does not work that way; you have to use C++ if that is really the
intention.

Regards,

Bill

···

=========================================================================
“Mills Thomas (app1tam)” app1tam@ups.com wrote:

But why does it really, REALLY mean that? Was there a reason for doing
this? Is it non-trivial to have ‘+=’ mean ‘append()’?

Drew

-----Original Message-----
From: Hal E. Fulton [mailto:hal9000@hypermetrics.com]
Sent: Monday, October 21, 2002 11:18 PM
To: ruby-talk@ruby-lang.org
Subject: Re: Things That Newcomers to Ruby Should Know (10/16/02)

It’s a feature. :slight_smile: The notation a+=b really, REALLY
means a = a + b. There is a + operator, but never a
+= operator, in Ruby (or any other assignment).

Hal

It’s non-sensical. << exists only as Array#<<, String#<<, and IO#<<
and means three different things. Array#<< is the same as
Array#push, IO#<< is similar to IO#puts, and String#<< is the same
as String#concat. Do you wish to create language exceptions for
three classes? How would 1.append(2) work (to use your notation)?
Why should there be exceptions to the object/language model in this
case?

-austin
– Austin Ziegler, austin@halostatue.ca on 2002.10.23 at 12.00.16

···

On Thu, 24 Oct 2002 00:23:33 +0900, Mills Thomas (app1tam) wrote:

-----Original Message----- From: Hal E. Fulton
It’s a feature. :slight_smile: The notation a+=b really, REALLY means a = a +
b. There is a + operator, but never a += operator, in Ruby (or
any other assignment).
But why does it really, REALLY mean that? Was there a reason for
doing this? Is it non-trivial to have ‘+=’ mean ‘append()’?

It’s fairly trivial to change the behavior, but the
overall impact on the language is nontrivial.

You wouldn’t want it to mean “append” for numbers,
right? What about the zillion other classes that
exist or might be defined?

Currently += simply is not an operator on
its own. To make it independent of + is a
major language change, IMO.

Right now it’s simple and regular, and unless
you’re counting milliseconds you don’t care
that an intermediate object is created.

Well, there are times you do care. See the
threads chapter in The Ruby Way.

Hal

···

----- Original Message -----
From: “Mills Thomas (app1tam)” app1tam@ups.com
To: “ruby-talk ML” ruby-talk@ruby-lang.org
Sent: Wednesday, October 23, 2002 10:23 AM
Subject: Re: Things That Newcomers to Ruby Should Know (10/16/02)

But why does it really, REALLY mean that? Was there a reason for doing
this? Is it non-trivial to have ‘+=’ mean ‘append()’?

Use Case:

begin
msgPrefix = "You have an error in line "

rescue
msg = msgPrefix
msg += lineNum
msg += ", which means that …"
end

There are other ways to code, of course. But in this case,
appending to msg would have the side effect of changing
msgPrefix, since they start by sharing a pointer to the same
object.

Very much a violation of least-surprise principle.

Hi Hal,

In my opinion, for any “reasonable” programmer, it is usually not the
milliseconds that causes concerns, but probably when the object is large
and/or complex. In that case then I think usually we tell them that Ruby
provides many methods that can modify the original object directly,
without the need of intermediate object (but of course we also warn them
about the aliasing/side-effects).

If a person has a C++ background, then probably the concept of creation of
intermediate object is troubling, because one of the many advices in C++
books is something like:

"When you pass an argument to a function, in general it is better to

pass it by reference instead of pass by value, because pass by value can
be much more expensive as it may involve the creation of an intermediate
object, while pass by reference will not." (To avoid modifying the
original object then the “const” type specifier is used.)

Therefore, a person with a C++ background, who is used to avoiding the
creation of unnecessary intermediate objects, will be surprised that Ruby
does it all the time in its ‘+=’ operator. (Furthermore, the creation
of equivalent intermediate objects may even be more “expensive” in Ruby
than in C++ in absolute terms.)

Therefore, this type of question is, in my opinion, usually not originated
by practicality concern as much as caused by the differences in “school of
thoughts” in the programming world. C++ is more about
(computer’s) performance, while Ruby is more about (programmer’s) fun. :slight_smile:

Regards,

Bill

···

Hal E. Fulton hal9000@hypermetrics.com wrote:

Right now it’s simple and regular, and unless
you’re counting milliseconds you don’t care
that an intermediate object is created.

Hi –

If a person has a C++ background, then probably the concept of creation of
intermediate object is troubling, because one of the many advices in C++
books is something like:

"When you pass an argument to a function, in general it is better to

pass it by reference instead of pass by value, because pass by value can
be much more expensive as it may involve the creation of an intermediate
object, while pass by reference will not." (To avoid modifying the
original object then the “const” type specifier is used.)

Therefore, a person with a C++ background, who is used to avoiding the
creation of unnecessary intermediate objects, will be surprised that Ruby
does it all the time in its ‘+=’ operator. (Furthermore, the creation
of equivalent intermediate objects may even be more “expensive” in Ruby
than in C++ in absolute terms.)

I don’t think “a += ‘str’” (or whatever) is creating an intermediate
object though, at least not in the sense that I understand the term.
It’s just performing an assignment, not doing anything extra.

Therefore, this type of question is, in my opinion, usually not originated
by practicality concern as much as caused by the differences in “school of
thoughts” in the programming world. C++ is more about
(computer’s) performance, while Ruby is more about (programmer’s) fun. :slight_smile:

I won’t argue with that :slight_smile: though it’s important to remember that
there’s nothing secret or subterranean about += in Ruby. It’s just a
way of performing an assignment – so if that isn’t what one wants
(for performance or other reasons), one has all the information
necessary to decide not to use it.

David

···

On Thu, 24 Oct 2002, William Djaja Tjokroaminata wrote:


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

dblack@candle.superlink.net wrote:

I don’t think “a += ‘str’” (or whatever) is creating an intermediate
object though, at least not in the sense that I understand the term.
It’s just performing an assignment, not doing anything extra.

Hi David,

Probably “intermediate” is not an exact terminology; maybe “new” object is
a better one? This can be shown by

a = 'str'
puts a.id    # -> some number
a << 'str'
puts a.id    # -> number unchanged (in-place modification)
a += 'str'
puts a.id    # -> number changed (a new object is created)

I think people with C++ background are used to the concept or convention
that ‘+=’ means in-place modification while ‘= self + something’ means a
new object creation. I think that is how we usually control performance
in C++: we prefer to use ‘+=’ unless the use of ‘=’ is necessary. The
aliasing/side-effects to other variables is of no concern because usually
the ‘=’ operator is overloaded (but then if someone forgets to overload
the ‘=’ operator then it may create a bug… :slight_smile: )

Regards,

Bill

Therefore, a person with a C++ background, who is used to
avoiding the creation of unnecessary intermediate objects, will
be surprised that Ruby does it all the time in its ‘+=’
operator. (Furthermore, the creation of equivalent intermediate
objects may even be more “expensive” in Ruby than in C++ in
absolute terms.)
I don’t think “a += ‘str’” (or whatever) is creating an
intermediate
object though, at least not in the sense that I understand the
term.
It’s just performing an assignment, not doing anything extra.

It’s creating an intermediate object that then becomes the original
object, in a sense. I think that the C++ programmer – where
references are often used like “safe” or “pretty” pointers, would
expect the following code to print out the same Object#ID both times
– and it doesn’t. It doesn’t because you’re creating a composite
object (a + “bar”) and then making a refer to that object rather
than the original a.

a = "Foo"
puts "a.id: #{a.id}"
a += "bar"
puts "a.id: #{a.id}"

I can see where it might be confusing, but as long it’s made clear
that a += b is the same as a = a + b, then even C++ programmers
shouldn’t expect a to point to the same object any longer (because
‘+’ would likely create an intermediate object).

-austin
– Austin Ziegler, austin@halostatue.ca on 2002.10.24 at 12.59.45

···

On Thu, 24 Oct 2002 20:21:54 +0900, dblack@candle.superlink.net wrote:

On Thu, 24 Oct 2002, William Djaja Tjokroaminata wrote:

Hi –

Therefore, a person with a C++ background, who is used to
avoiding the creation of unnecessary intermediate objects, will
be surprised that Ruby does it all the time in its ‘+=’
operator. (Furthermore, the creation of equivalent intermediate
objects may even be more “expensive” in Ruby than in C++ in
absolute terms.)
I don’t think “a += ‘str’” (or whatever) is creating an
intermediate
object though, at least not in the sense that I understand the
term.
It’s just performing an assignment, not doing anything extra.

It’s creating an intermediate object that then becomes the original
object, in a sense. I think that the C++ programmer – where

I think that’s kind of a roundabout way to describe it though. I
would say: it’s creating a new object, and assigning a reference to
that object to a variable which previously held a reference to a
different object.

references are often used like “safe” or “pretty” pointers, would
expect the following code to print out the same Object#ID both times
– and it doesn’t. It doesn’t because you’re creating a composite
object (a + “bar”) and then making a refer to that object rather
than the original a.

Right – what I was saying was just that “intermediate object” didn’t
sound like the right term to me, just as when you say:

a = “Hello”

you’re just creating an object (which I would not consider an
intermediate object). I guess I think of intermediate object creation
as, for instance:

a = [1,2,3]
b = a.map {|x| x * 2} .map {|x| x * 3}

where there’s an anonymous array being created en route to the
eventual creation of the array referred to by ‘b’.

David

···

On Fri, 25 Oct 2002, Austin Ziegler wrote:

On Thu, 24 Oct 2002 20:21:54 +0900, dblack@candle.superlink.net > wrote:

On Thu, 24 Oct 2002, William Djaja Tjokroaminata wrote:


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

you’re just creating an object (which I would not consider an
intermediate object). I guess I think of intermediate object creation
as, for instance:

a = [1,2,3]
b = a.map {|x| x * 2} .map {|x| x * 3}

where there’s an anonymous array being created en route to the
eventual creation of the array referred to by ‘b’.
BTW, ONE or TWO intermediate objects?
So, a.map {|x| x*2} must be created, but right after the assignment will
this object be deleted?

Gergo

±[Kontra, Gergely @ Budapest University of Technology and Economics]-+

    Email: kgergely@mcl.hu,  kgergely@turul.eet.bme.hu          |

URL: turul.eet.bme.hu/~kgergely Mobile: (+36 20) 356 9656 |
±------“Olyan langesz vagyok, hogy poroltoval kellene jarnom!”-------+
.
Magyar php mirror es magyar php dokumentacio: http://hu.php.net

Hello Gergely,

Friday, October 25, 2002, 3:09:16 PM, you wrote:

b = a.map {|x| x * 2} .map {|x| x * 3}
BTW, ONE or TWO intermediate objects?
So, a.map {|x| x*2} must be created, but right after the assignment will
this object be deleted?

ONE intermediate object and ONE assigned to b. this intermediate
object will be garbage coolected with all other ones. btw, seasoned ruby
programmers wrote:

a.map {|x| x * 2} .map! {|x| x * 3}

(replace second “map” to “map!”).

···


Best regards,
Bulat mailto:bulatz@integ.ru