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

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.

On Dec 1, 2007 10:55 AM, samppi [email protected] wrote:

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

Hi –

On Sun, 2 Dec 2007, Pat M. wrote:

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-will-rubyist

David

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.

On Dec 1, 1:13 pm, “David A. Black” [email protected] wrote:

“reverse!”

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.comfor 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

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, 4:13 pm, MonkeeSage [email protected] wrote:

of ending the names of mutating methods with an exclamation point to
or “map”…and in any case, Ruby is different enough in syntax and

mutation of the receiver is “dangerous”, and label everything that
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

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.

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

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

Consistency helps make things somehow predictable, but sometimes it’s

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.

Hi –

On Sun, 2 Dec 2007, MonkeeSage wrote:

distinguish them from similar accessor methods, like “reverse” vs.
style that it shouldn’t even matter.

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.comfor 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.

b # => [1, 2, 3]
Well, people coming from Ruby wouldn’t do that :slight_smile: 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

Hi –

On Sun, 2 Dec 2007, John J. 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

I think the whole question of what the best names were for those
methods would have to be revisited. Since push and pop are, by
convention and tradition, object-mutating methods, it would be very
weird to suddenly have “non-dangerous” versions of them that didn’t
change the object, and to define “danger” as behaving the way push and
pop are always (as far as I know) understood to behave.

David

From: “David A. Black” [email protected]

The thing to remember is that ! methods always exist (or should
always exist) in a pair with non-! counterparts.

Hmm. That makes sense to me in general, but I wrote a ! method
recently that has no non-! counterpart. A non-! counterpart
wouldn’t make sense in this case, and yet I feel the ! is reminding
me something special is going on with this method.

The particular case is a UI client library whose widgets are
hosted on a remote window server. The client is able to create
and initialize widget objects locally, without yet having
communicated with the remote server. Only when the instantiate!
method is finally called, do we go over the wire and instantiate
these widgets in the window server.

There is no non-! counterpart, but I feel the ! is very
appropriate for this method.

Regards,

Bill

On Dec 2, 2007, at 1:44 AM, David A. Black wrote:

have
pop are always (as far as I know) understood to behave.

David
I understand where you’re coming from completely with the tradition
and convention, but sometimes tradition could be broken.
I was just being hypothetical, after playing with Cocoa and Objective-
C lately, where most container classes come in mutable and immutable
varieties, methods there to work on immutable containers have no
choice but to return a new container. (where the new one can be
either mutable or immutable, since creation uses the same shared
initializer)
Just to illustrate the point if there were a purpose for ! with push
and pop.
Since we don’t have immutable containers in Ruby, there’s not a point
to these methods having a bang.
They inherently bang.
Just a hypothetical.
Since Ruby is Ruby, the flavor is distinctly mostly mutable
objects… yummy!

Hi –

On Sun, 2 Dec 2007, Bill K. wrote:

The particular case is a UI client library whose widgets are
hosted on a remote window server. The client is able to create
and initialize widget objects locally, without yet having
communicated with the remote server. Only when the instantiate!
method is finally called, do we go over the wire and instantiate
these widgets in the window server.

There is no non-! counterpart, but I feel the ! is very
appropriate for this method.

My immediate thought, as a user of the method, would be: why? :slight_smile: If
it’s not part of a pair, then the ! is usually a sign that it should
be named something else – something where the name itself tells you
about what’s happening (like push and pop).

I don’t mean to sound like the ! police. It’s just that I’ve never
seen a usage pattern that, in my opinion, came close to being as
useful and elegant as the one Matz employs and recommends. The
problem, basically, is that the ! itself has no meaning. It’s not even
as meaningful as ?, which fairly clearly connotes a boolean. So the !
is entirely what we make of it, and I haven’t seen any improvements to
the approach Matz takes among the variants of usage. As a general,
contextless warning sign, it’s hopelessly unclear and impossible to
interpret. In !/non-! pairs, it starts to be able to say something.

The only standalone ! methods I can recall seeing that made sense to me
are the ones in Builder, by Jim W., where the ! is a kind of
escape from having the method name be automatically used as the name
of an XML element. Come to think of it, those aren’t really
standalone, since the equivalent non-! methods do exist.

David

Hi –

On Tue, 4 Dec 2007, John J. wrote:

bloat.
weird to suddenly have “non-dangerous” versions of them that didn’t
change the object, and to define “danger” as behaving the way push and
pop are always (as far as I know) understood to behave.

David
I understand where you’re coming from completely with the tradition and
convention, but sometimes tradition could be broken.

Yes, of course the parser will let you do:

def greet!
puts “Hi”
end

def valid?
@x = 3
end

but why would you want to? :slight_smile: The point is that in this case there is
only tradition and convention – meaning, Matz added these !-methods
to the language so that there could be dangerous/non-dangerous
method pairs. Any rededication of ! to another purpose (like, a vague
stylistic flourish meaning “What a strange method!” or a more general
“This changes its receiver” signal) just means that the whole thing
becomes method-name soup and has no meaning.

So it’s not pure stodginess on my part when I say: let’s let the ! do
what it’s supposed to do. If we don’t, then we’ve lost what I think is
an ingenious and extraordinarily expressive technique.

I was just being hypothetical, after playing with Cocoa and Objective-C
lately, where most container classes come in mutable and immutable varieties,
methods there to work on immutable containers have no choice but to return a
new container. (where the new one can be either mutable or immutable, since
creation uses the same shared initializer)
Just to illustrate the point if there were a purpose for ! with push and pop.
Since we don’t have immutable containers in Ruby, there’s not a point to
these methods having a bang.
They inherently bang.

They inherently change their receivers, but that’s a separate matter
from the !.

Just a hypothetical.
Since Ruby is Ruby, the flavor is distinctly mostly mutable objects… yummy!

And, one hopes, mostly non-dangerous operations :slight_smile: which is why it’s
nice to have the ! to signal those “evil twin” methods.

David

On Dec 4, 5:23 am, MonkeeSage [email protected] wrote:

used that way at least a few times in stdlib.

  • Oh yeah, and I just remembered #power! (on Bignum I think) which
    isn’t dangerous and doesn’t modify the receiver…it just raises to a
    power. Where the heck did the bang come from?!

Regards,
Jordan

Few more methods where the bang only indicates in-place operation:

String#succ!, Array#reverse!, Array#collect!, Array#sort!

Regards,
Jordan

On Dec 4, 3:02 am, “David A. Black” [email protected] wrote:

They inherently change their receivers, but that’s a separate matter
from the !.

Well…99% of the time it is, except when the ! only serves to
indicate that it operates in-place (String#reverse!, Hash#update!, and
probably a few others I can’t think of offhand*). That’s why I
characterized the ! as “either-or-both” regarding in-place/dangerous.
Even if it’s not a good idea or breaks with the common usage, it is
used that way at least a few times in stdlib.

  • Oh yeah, and I just remembered #power! (on Bignum I think) which
    isn’t dangerous and doesn’t modify the receiver…it just raises to a
    power. Where the heck did the bang come from?!

Regards,
Jordan

Hi –

On Tue, 4 Dec 2007, MonkeeSage wrote:

Even if it’s not a good idea or breaks with the common usage, it is

String#succ!, Array#reverse!, Array#collect!, Array#sort!

In-place modification is, I think, definitely the most common form of
!-style “danger”. It’s not the only form, though.

David

Hi –

On Tue, 4 Dec 2007, MonkeeSage wrote:

On Dec 4, 3:02 am, “David A. Black” [email protected] wrote:

They inherently change their receivers, but that’s a separate matter
from the !.

Well…99% of the time it is, except when the ! only serves to
indicate that it operates in-place (String#reverse!, Hash#update!, and
probably a few others I can’t think of offhand*). That’s why I
characterized the ! as “either-or-both” regarding in-place/dangerous.

I’m not sure I follow, so this may not be relevant, but in-place
changes (changes to the receiver) are one form of “danger”, in this
sense. They’re just not the only form.

Even if it’s not a good idea or breaks with the common usage, it is
used that way at least a few times in stdlib.

I don’t know of any that don’t come in pairs, where the ! one
indicates “danger” (reverse/reverse!, exit/exit!, etc.).

  • Oh yeah, and I just remembered #power! (on Bignum I think) which
    isn’t dangerous and doesn’t modify the receiver…it just raises to a
    power. Where the heck did the bang come from?!

Good question. I see this in ri but I don’t see it actually on any
objects. I’m not sure what it is.

David