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-will-rubyist
>>
>> 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!
>
> "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.rubypal.com for details and 2008 announcements!