[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

Why are "Array#push" and "pop" not "push!" and "pop!"?

Joshua Choi

12/1/2007 6:51:00 PM

As a novice in Ruby, I love its elegance and consistence; it's now one
of my favorite languages. One of my favorite features is the practice
of ending the names of mutating methods with an exclamation point to
distinguish them from similar accessor methods, like "reverse" vs.
"reverse!"

I'm curious, though, about an apparent inconsistency with this rule in
Array: push, pop, shift, and unshift. All four methods modify objects
in-place, yet they don't have an "!". Why is this?

The only reason I can think of is that they lack "!"s in other
languages, which is a pretty tenuous reason at best--not many
languages name their methods "empty?" or "map!" instead of "is_empty"
or "map"...and in any case, Ruby is different enough in syntax and
style that it shouldn't even matter.
29 Answers

Pat Maddox

12/1/2007 7:04:00 PM

0

On Dec 1, 2007 10:55 AM, samppi <rbysamppi@gmail.com> wrote:
> As a novice in Ruby, I love its elegance and consistence; it's now one
> of my favorite languages. One of my favorite features is the practice
> of ending the names of mutating methods with an exclamation point to
> distinguish them from similar accessor methods, like "reverse" vs.
> "reverse!"
>
> I'm curious, though, about an apparent inconsistency with this rule in
> Array: push, pop, shift, and unshift. All four methods modify objects
> in-place, yet they don't have an "!". Why is this?
>
> The only reason I can think of is that they lack "!"s in other
> languages, which is a pretty tenuous reason at best--not many
> languages name their methods "empty?" or "map!" instead of "is_empty"
> or "map"...and in any case, Ruby is different enough in syntax and
> style that it shouldn't even matter.
>
>

! doesn't signify a mutating method, it signifies a destructive
version of a method. Per your example, #reverse revers the array
without changing it, whereas #reverse! is destructive. #push and #pop
do not have a nondestructive version.

Pat

David A. Black

12/1/2007 7:14:00 PM

0

Hi --

On Sun, 2 Dec 2007, Pat Maddox wrote:

> On Dec 1, 2007 10:55 AM, samppi <rbysamppi@gmail.com> wrote:
>> As a novice in Ruby, I love its elegance and consistence; it's now one
>> of my favorite languages. One of my favorite features is the practice
>> of ending the names of mutating methods with an exclamation point to
>> distinguish them from similar accessor methods, like "reverse" vs.
>> "reverse!"
>>
>> I'm curious, though, about an apparent inconsistency with this rule in
>> Array: push, pop, shift, and unshift. All four methods modify objects
>> in-place, yet they don't have an "!". Why is this?
>>
>> The only reason I can think of is that they lack "!"s in other
>> languages, which is a pretty tenuous reason at best--not many
>> languages name their methods "empty?" or "map!" instead of "is_empty"
>> or "map"...and in any case, Ruby is different enough in syntax and
>> style that it shouldn't even matter.
>>
>>
>
> ! doesn't signify a mutating method, it signifies a destructive
> version of a method. Per your example, #reverse revers the array
> without changing it, whereas #reverse! is destructive. #push and #pop
> do not have a nondestructive version.

For more along the same lines, see:
http://dablog.rubypal.com/2007/8/15/bang-methods-or-danger-wi...


David

--
Upcoming training by David A. Black/Ruby Power and Light, LLC:
* Intro to Rails, London, UK, December 3-6 (by Skills Matter)
See http://www.r... for details and 2008 announcements!

John Joyce

12/1/2007 9:36:00 PM

0

some languages and libraries include silly or useless things to
achieve symmetry and a peculiar consistency.
It's not always important or necessary.
Some things are just unique or different and don't need symmetry or
consistency or don't have it and no reason.

MonkeeSage

12/1/2007 10:14:00 PM

0

On Dec 1, 1:13 pm, "David A. Black" <dbl...@rubypal.com> wrote:
> Hi --
>
>
>
> On Sun, 2 Dec 2007, Pat Maddox wrote:
> > On Dec 1, 2007 10:55 AM, samppi <rbysam...@gmail.com> wrote:
> >> As a novice in Ruby, I love its elegance and consistence; it's now one
> >> of my favorite languages. One of my favorite features is the practice
> >> of ending the names of mutating methods with an exclamation point to
> >> distinguish them from similar accessor methods, like "reverse" vs.
> >> "reverse!"
>
> >> I'm curious, though, about an apparent inconsistency with this rule in
> >> Array: push, pop, shift, and unshift. All four methods modify objects
> >> in-place, yet they don't have an "!". Why is this?
>
> >> The only reason I can think of is that they lack "!"s in other
> >> languages, which is a pretty tenuous reason at best--not many
> >> languages name their methods "empty?" or "map!" instead of "is_empty"
> >> or "map"...and in any case, Ruby is different enough in syntax and
> >> style that it shouldn't even matter.
>
> > ! doesn't signify a mutating method, it signifies a destructive
> > version of a method. Per your example, #reverse revers the array
> > without changing it, whereas #reverse! is destructive. #push and #pop
> > do not have a nondestructive version.
>
> For more along the same lines, see:http://dablog.rubypal.com/2007/8/15/bang-methods-or-danger-wi...
>
> David
>
> --
> Upcoming training by David A. Black/Ruby Power and Light, LLC:
> * Intro to Rails, London, UK, December 3-6 (by Skills Matter)
> Seehttp://www.ruby... details and 2008 announcements!

"Dangerous" seems kind of ambiguous. Does it mean that the code does
something other than I expect? Or, that it will break code relying on
the non-bang version? Or some combination? Or something else entirely?

E.g., people coming from Haskell / Clean would likely say that *any*
mutation of the receiver is "dangerous", and label everything that
doesn't operate on a copy with a "!"

a = [1,2]
b = a
def impure!(a)
a.replace([1,2,3])
end
impure!(a) # dangerous!
b # => [1, 2, 3]

Regards,
Jordan

Simon Schuster

12/1/2007 11:03:00 PM

0

this is a comment I agree with, that I haven't been able to articulate
quite so well.

it's sometimes even a hindrance, as it places everything on such an
"even field" as to be impossible to sort through.

On Dec 1, 2007 1:36 PM, John Joyce <dangerwillrobinsondanger@gmail.com> wrote:
> some languages and libraries include silly or useless things to
> achieve symmetry and a peculiar consistency.
> It's not always important or necessary.
> Some things are just unique or different and don't need symmetry or
> consistency or don't have it and no reason.
>
>

MonkeeSage

12/1/2007 11:28:00 PM

0

On Dec 1, 4:13 pm, MonkeeSage <MonkeeS...@gmail.com> wrote:
> On Dec 1, 1:13 pm, "David A. Black" <dbl...@rubypal.com> wrote:
>
>
>
> > Hi --
>
> > On Sun, 2 Dec 2007, Pat Maddox wrote:
> > > On Dec 1, 2007 10:55 AM, samppi <rbysam...@gmail.com> wrote:
> > >> As a novice in Ruby, I love its elegance and consistence; it's now one
> > >> of my favorite languages. One of my favorite features is the practice
> > >> of ending the names of mutating methods with an exclamation point to
> > >> distinguish them from similar accessor methods, like "reverse" vs.
> > >> "reverse!"
>
> > >> I'm curious, though, about an apparent inconsistency with this rule in
> > >> Array: push, pop, shift, and unshift. All four methods modify objects
> > >> in-place, yet they don't have an "!". Why is this?
>
> > >> The only reason I can think of is that they lack "!"s in other
> > >> languages, which is a pretty tenuous reason at best--not many
> > >> languages name their methods "empty?" or "map!" instead of "is_empty"
> > >> or "map"...and in any case, Ruby is different enough in syntax and
> > >> style that it shouldn't even matter.
>
> > > ! doesn't signify a mutating method, it signifies a destructive
> > > version of a method. Per your example, #reverse revers the array
> > > without changing it, whereas #reverse! is destructive. #push and #pop
> > > do not have a nondestructive version.
>
> > For more along the same lines, see:http://dablog.rubypal.com/2007/8/15/bang-methods-or-danger-wi...
>
> > David
>
> > --
> > Upcoming training by David A. Black/Ruby Power and Light, LLC:
> > * Intro to Rails, London, UK, December 3-6 (by Skills Matter)
> > Seehttp://www.rubypal.com... and 2008 announcements!
>
> "Dangerous" seems kind of ambiguous. Does it mean that the code does
> something other than I expect? Or, that it will break code relying on
> the non-bang version? Or some combination? Or something else entirely?
>
> E.g., people coming from Haskell / Clean would likely say that *any*
> mutation of the receiver is "dangerous", and label everything that
> doesn't operate on a copy with a "!"
>
> a = [1,2]
> b = a
> def impure!(a)
> a.replace([1,2,3])
> end
> impure!(a) # dangerous!
> b # => [1, 2, 3]
>
> Regards,
> Jordan

In thinking about it a little bit and looking at the stdlib, I think
it is accurate to say that !-methods have one of these
characteristics:

1.) Modifies receiver in-place (e.g., String#succ!).
2.) Causes some side-effect that is incompatible or sufficiently
different from the non-bang version (e.g., Thread#kill!) -- i.e., is
"dangerous".
3.) Implies both 1 & 2 (e.g., String#gsub!).

So in regard to the question posed by the OP, it seems that yes, to be
perfectly consistent with the usual syntax, pop, push and un/shift
should be suffixed with a bang. However, like John said, sometimes it
just makes sense to break the syntax. And this is a perfect example;
those methods don't have any semantic meaning that does not fall under
the above characterization of !-methods (i.e., there would be no
"normal" version, just a bang version), and their names are perfectly
descriptive. Further, given the second characterization, people may
think they are somehow unusual from they way they work in other
languages (or just their "intuitive" sense). So there is really no
benefit to having them as !-methods.

Regards,
Jordan

John Joyce

12/1/2007 11:53:00 PM

0

To put it another way, consistency for consistency's sake alone is
not the goal.
Consistency helps make things somehow predictable, but sometimes it's
just bloat.

That said, if Ruby had immutable classes, it would be important to have
push # return a new Array object with the result of a push
push! # alter the Array object in place with the result of push
pop # return a new Array object with the result of a pop
pop! # alter the Array object in place with the result of pop

Simon Schuster

12/2/2007 12:27:00 AM

0

so the next question is do you think those could be useful additions?
or, can the push/pop/shift/unshift in that case (as opposed to the
equivalent! term) be gotten in some other way that makes the current
way (no ! methods at all) most advantageous/efficient, since both ends
can currently be achieved.

On Dec 1, 2007 3:52 PM, John Joyce <dangerwillrobinsondanger@gmail.com> wrote:
> To put it another way, consistency for consistency's sake alone is
> not the goal.
> Consistency helps make things somehow predictable, but sometimes it's
> just bloat.
>
> That said, if Ruby had immutable classes, it would be important to have
> push # return a new Array object with the result of a push
> push! # alter the Array object in place with the result of push
> pop # return a new Array object with the result of a pop
> pop! # alter the Array object in place with the result of pop
>
>

John Joyce

12/2/2007 2:39:00 AM

0


On Dec 1, 2007, at 6:26 PM, Christopher Anderson wrote:

> so the next question is do you think those could be useful additions?
> or, can the push/pop/shift/unshift in that case (as opposed to the
> equivalent! term) be gotten in some other way that makes the current
> way (no ! methods at all) most advantageous/efficient, since both ends
> can currently be achieved.
>
> On Dec 1, 2007 3:52 PM, John Joyce
> <dangerwillrobinsondanger@gmail.com> wrote:
>> To put it another way, consistency for consistency's sake alone is
>> not the goal.
>> Consistency helps make things somehow predictable, but sometimes it's
>> just bloat.
>>
>> That said, if Ruby had immutable classes, it would be important to
>> have
>> push # return a new Array object with the result of a push
>> push! # alter the Array object in place with the result of push
>> pop # return a new Array object with the result of a pop
>> pop! # alter the Array object in place with the result
>> of pop
>>
>>
>
Like I said, my top-posting pal, if Ruby had immutable classes...
I suppose it's possible to implement immutable Array and MutableArray
(we already have that one)
but how practical is it really?
I can understand wanting it to prevent objects getting stepped on
even accidentally, Cocoa does that a lot.

David A. Black

12/2/2007 7:41:00 AM

0

Hi --

On Sun, 2 Dec 2007, MonkeeSage wrote:

> On Dec 1, 1:13 pm, "David A. Black" <dbl...@rubypal.com> wrote:
>> Hi --
>>
>>
>>
>> On Sun, 2 Dec 2007, Pat Maddox wrote:
>>> On Dec 1, 2007 10:55 AM, samppi <rbysam...@gmail.com> wrote:
>>>> As a novice in Ruby, I love its elegance and consistence; it's now one
>>>> of my favorite languages. One of my favorite features is the practice
>>>> of ending the names of mutating methods with an exclamation point to
>>>> distinguish them from similar accessor methods, like "reverse" vs.
>>>> "reverse!"
>>
>>>> I'm curious, though, about an apparent inconsistency with this rule in
>>>> Array: push, pop, shift, and unshift. All four methods modify objects
>>>> in-place, yet they don't have an "!". Why is this?
>>
>>>> The only reason I can think of is that they lack "!"s in other
>>>> languages, which is a pretty tenuous reason at best--not many
>>>> languages name their methods "empty?" or "map!" instead of "is_empty"
>>>> or "map"...and in any case, Ruby is different enough in syntax and
>>>> style that it shouldn't even matter.
>>
>>> ! doesn't signify a mutating method, it signifies a destructive
>>> version of a method. Per your example, #reverse revers the array
>>> without changing it, whereas #reverse! is destructive. #push and #pop
>>> do not have a nondestructive version.
>>
>> For more along the same lines, see:http://dablog.rubypal.com/2007/8/15/bang-methods-or-danger-wi...
>>
>> David
>>
>> --
>> Upcoming training by David A. Black/Ruby Power and Light, LLC:
>> * Intro to Rails, London, UK, December 3-6 (by Skills Matter)
>> Seehttp://www.ruby... details and 2008 announcements!
>
> "Dangerous" seems kind of ambiguous. Does it mean that the code does
> something other than I expect? Or, that it will break code relying on
> the non-bang version? Or some combination? Or something else entirely?

It varies. Just think of it as a "heads up". It means that you need to
make sure you really know what the method does.

A classic example is:

"abc".gsub!(/x/, "z")

which returns nil, because no substitutions have occurred. The ! warns
you that you really need to know what's going on -- in this case, both
that the receiver will be changed if there are substitutions, and that
the return value is different from that of the non-! version when
there aren't.

> E.g., people coming from Haskell / Clean would likely say that *any*
> mutation of the receiver is "dangerous", and label everything that
> doesn't operate on a copy with a "!"
>
> a = [1,2]
> b = a
> def impure!(a)
> a.replace([1,2,3])
> end
> impure!(a) # dangerous!
> b # => [1, 2, 3]

Well, people coming from Ruby wouldn't do that :-) The thing to
remember is that ! methods always exist (or should always exist) in a
pair with non-! counterparts. The ! is not just an exclamation of
surprise; it's supposed to mean something *in relation to* its
context.


David

--
Upcoming training by David A. Black/Ruby Power and Light, LLC:
* Intro to Rails, London, UK, December 3-6 (by Skills Matter)
See http://www.r... for details and 2008 announcements!