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

just means that the whole thing
becomes method-name soup and has no meaning.

That is not true. I agree that it should not be used
in other ways than how pretty everyone else uses it.

However, it does not have no meaning anymore, it
simply has a different meaning now. If you want to
use it (i.e define this different meaning) and how
you want to use it, is up to you - for example,
you could do something like:

def nuke!
FileUtils.rm_rf /playing_games_during_worktime # boss coming in!
end

And you would still be aware that the method does
something dangerous.

I used to do this years ago, until I later found out
I hated to be surprised by methods with ! which
behave differently :wink:

Hi –

On Tue, 4 Dec 2007, Marc H. wrote:

just means that the whole thing
becomes method-name soup and has no meaning.

That is not true. I agree that it should not be used
in other ways than how pretty everyone else uses it.

However, it does not have no meaning anymore, it
simply has a different meaning now.

Not that I’ve heard. I’ll defer to Matz on that one.

If you want to use it (i.e define this different meaning) and how
you want to use it, is up to you - for example, you could do
something like:

def nuke!
FileUtils.rm_rf /playing_games_during_worktime # boss coming in!
end

And you would still be aware that the method does
something dangerous.

Yes, as I said before, we can all do whatever we want with !, and end
up with no convention and no pattern and therefore no meaning. If we
all invent new meanings for it, then it has none, in the sense that
when I see it, I won’t know what it means.

The parser will certainly let you do it. I just have not seen any
evidence that anyone has any ideas on this that are remotely as good
as Matz’s. So I’ve never understood what the temptation is to
improvise new meanings for it.

I used to do this years ago, until I later found out
I hated to be surprised by methods with ! which
behave differently :wink:

But that’s the point – the ! tells you that they behave
differently from their “non-dangerous” counterparts. That’s the
ingenuity of it.

David

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

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.

Don’t mind me, I’m just over-analyzing. :stuck_out_tongue_winking_eye: After remaking that
“danger” can be ambiguous above, I posted a characterization of !
where I tried to disambiguate “danger” in the following way: “Causes
some side-effect that is incompatible or sufficiently different from
the non-bang version”. Since everything is “dangerous” in ruby from
the perspective of a haskeller, I thought it might be helpful to
differentiate between mutation of the receiver (not generally
considered dangerous in ruby), and incompatible/unexpected behavior as
compared to the non-bang version. Most bang-methods, I think, do both.

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

I agree. That was one of my reasons for not supporting “push!” –
along with the fact that the method name is fully descriptive, and
that a ! suffix would be confusing, it would be unbalanced (q.v.,
previous post).

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

It appears to be an alias of an alias (power! → ** → rpower).
Bignum#rpower returns a new Rational, so, indeed, the operation is non-
dangerous and does not mutate the receiver…I guess matz just had an
extra “!” lying around and didn’t want to waste it, heh. :wink:

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.comfor details and 2008 announcements!

Regards,
Jordan

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

My immediate thought, as a user of the method, would be: why? :slight_smile:
Exactly. Then I would feel I’ve succeeded in using the bang
notation: “Why?” seems a reasonable question to ask when seeing
an unfamiliar bang method. (That such a method may or may not
turn out to be paired with a non-bang method has no bearing on
this: one still has to ask Why? in either case!)

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

Eh… I actually did consider naming it “instantiate_on_remote” or
something… But in the context of using this particular library, I
like the name “instantiate!” even better. Sure, it’s a matter of taste;
but it feels right to me - and I’m pleased ruby has allowed me this
form of expression.

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.

I don’t see how one can infer any particular meaning from requiring
! methods to be paired with non-! methods. Seeing an unfamiliar !
method always boils down to the same question: What in particular is
special or unusual about the behavior of this method? That such a
method may have a non-! pair seems only interesting from the
standpoint of determining which method to use when writing the code
in the first place. When reading existing code, one either knows
what’s special about a particular ! method, or one doesn’t.

If I see exit! in code, does the mere existence of a non-! exit
automatically confer to me that the ! form is special because it,
“Exits the process immediately. No exit handlers are run.” ?
No, I got that from ri

When I see an unfamiliar ! method, is my first thought, “say, I
wonder if this method also has a non-! equivalent?” I’m pretty sure
I just think: what does this method do, and what’s special about it?

Maybe I should instead be asking what you had in mind when you said,
“In !/non-! pairs, it starts to be able to say something.” What is
this something that is said by a paired !/non-! relationship?

Regards,

Bill

Hi –

On Wed, 5 Dec 2007, Bill K. wrote:

Maybe I should instead be asking what you had in mind when you said,
“In !/non-! pairs, it starts to be able to say something.” What is
this something that is said by a paired !/non-! relationship?

I know what you mean about ri, but I check ri (or equivalent) for
every method, at some point, whether it has a ! or not, so I don’t
think just peppering one’s methods with occasional !'s really adds
anything from that perspective.

I think I’m about tapped out on this one, but I’ll give it another
shot :slight_smile: I really like the convention that Matz uses, and every other
use of ! in method names has struck me as impressionistic and
uncommunicative. It would certainly be possible to have
exit/exit_without_finalizers and reverse/reverse_in_place. I just
think that Matz’s abstraction of these as “dangerous”, and dedication
of the ! to expressing that abstraction, is strikingly elegant and has
the weight of some kind of logic behind it. It hits a narrower target
– it means that there’s a whole class of tricky (or whatever) methods
that have to find some other way to express their trickiness – but I
think it’s worth it.

David

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

[…] I just
think that Matz’s abstraction of these as “dangerous”, and dedication
of the ! to expressing that abstraction, is strikingly elegant and has
the weight of some kind of logic behind it. It hits a narrower target
– it means that there’s a whole class of tricky (or whatever) methods
that have to find some other way to express their trickiness – but I
think it’s worth it.

Ah. I think I understand your viewpoint better now; thanks.

(And if nothing else, at least we can both agree on the “hits a
narrower target” part. )

Regards,

Bill

On Dec 4, 2007 1:04 PM, Bill K. [email protected] wrote:

Well, slice(-1) and slice!(-1) are equivalents for pop (non-modifying)
and pop! (modifying), right?

Good point. :slight_smile:

I remember having the same question about shift/unshift when I first
learned Ruby. I remember doing something like the following:

item = items.shift!

…and I was surprised to see a NoMethodError. It seemed to violate
the rule I supposed existed: all destructive methods end in !

It is an interesting debate, but I suppose it’s a bit of a moot point
now; it’s too late to change these basic methods, even if we wanted
to.

On Dec 4, 1:31 pm, Christian von Kleist [email protected] wrote:

of the ! to expressing that abstraction, is strikingly elegant and has
Regards,

Bill

Well, slice(-1) and slice!(-1) are equivalents for pop (non-modifying)
and pop! (modifying), right?

Well…that’s kind of cheating. Heh. :wink: Semantically, they are very
different; though pragmatically you get the same result. Kind of like
a car hitting you at 50 k/mph gets the same result as you hitting a
car at 50 k/mph, even though the car traveling 50 k/mph and yourself
traveling 50 k/mph are very different. For perhaps a better
analogy…these two do the same thing, even though they have very
different semantics and implementations:

p [1,2,3,4].last #=> 4

arr = [1,2,3,4]
count = 0
arr.each { | e |
if count == arr.size-1
p e
end
count += 1
}

=> 4

The first is obviously the correct choice, even though you can do
the second if you really wanted to.

Regards,
Jordan

Hi –

On Wed, 5 Dec 2007, Christian von Kleist wrote:

Good point. :slight_smile:

I remember having the same question about shift/unshift when I first
learned Ruby. I remember doing something like the following:

item = items.shift!

…and I was surprised to see a NoMethodError. It seemed to violate
the rule I supposed existed: all destructive methods end in !

We’re lucky that there’s no such rule. Imagine:

“string” <<! “more text”
array.clear!
obj.instance_variable_set!
(etc.)

:slight_smile:

The use of destructive-sounding names (or, where appropriate,
non-destructive-sounding ones plus the “danger” flag) works out well.
The only somewhat anomalous case I know of is delete(!), where
String#delete is not destructive but Array#delete is. I’m not sure why
those differ from each other in that respect.

David