Tobias Reif wrote:
> Matz,
> 
> 
> > |I'd like to have bang and non-bang versions of each and every method.
> > |The names should just differ in the !, like collect and collect!
> > 
> > Like scheme?  But imagine that every destructive (in other words, self
> > modifying) method has ! in its name, Ruby programs would be filled
> > with bangs.  It might be informative, but let's face it, it's ugly.
> 
> 
> By reading the docs, everyone can find out how each method acts.
> But a stringent concept would help programmers to always know how a 
> method behaves in this aspect; which would benefit the Princple of Least 
> Surprise.
> 
> If we were in the early phase (not having to consider finalized 
> decisions, and backwards-compatibility):
> 
> If destructive methods are more often used that non-destructive one, the 
> "default" (shorter name) could be destructive.
> Otherwise, the default is to be non-destructive, like now.
> 
> I agree that '!'s all over the place could be ugly.
> So maybe:
> All methods are destructive by default, and every method has a 
> counterpart which is non-destructive; since it returns a copy, _c could 
> be appended (exact naming convention is just a detail of a stringent 
> concept.).
> 
> Ruby is already at 1.7.x, so it's too late for all this.
> Or is it?
> Conventions for writing publicly available Ruby methods are interesting.
> And Ruby 2 too.
> 
> Here are more thoughts:
> 
> 
> I'm currently learning Ruby, and I like it a lot.
> 
> At first I thought that all methods return modified copies,
> and only "!" methods modify the original.
> 
> Then I ran into many problems, because []=
> is bang without having a "!" appended, and doesn't have
> a non-bang version.
> 
> AFAIK, there are many more methods that are destructive but don't
> declare that in their name:
> clear, delete, delete_at, delete_if, fill, pop, push, replace, shift,
> unshift, Array#filter.

"!" tells you "it's more dangerous to use it than the non-bang method". 
I don't thinks it's good to have for each method both, a destructive and 
non-destructive version. There is no Array#delete!, because it's obvious 
that delete is destructive; for the non-destructive version you might use 
Array#reject. 

> It would be OK if all methods are bang by default, and have some
> version which is non-bang.

I don't like that. How to name the non-bang methods?
Changing this would break all Ruby code out there.

> But I think any stringent concept and naming convention not only
> would immensely help beginners,
> but add to Ruby's semantic richness and clarity.
> Something like
> "Beware, however, that there are a fair number of destructive methods
> that don't have an '!' "
> in the FAQs it not a nice discovery for everyone learning Ruby.

Once again, "!" only marks a method as dangerous, that do not means, others
without it are less dangerous (destructive). 
For me it's obvious that

  a.delete_if {|i| i > 2}

would delete all elements larger than 2 from Array a. As mentioned above, I'd write

  b = a.reject {|i| i > 2}

for the non-destructive counterpart. 
For me, this is PoLS. 

If a method has a "!" version, you exactly know what each does. 
If there is no "!" version then take a look at the method name, if it sounds
destructive (delete, set []=, push, pop) then the method is destructive. 

> "The plain version takes a copy of the receiver, makes its change to it,
> and returns the copy. The version with the ! modifies the receiver in 
> place."
> is a rule with many non-obvious exceptions.
> This fact which generates confusion, and sabotages the
> "Princple of Least Surprise" in a very relevant way.
> 
> Any concept would solve the problem, as long as it's 100% stringent.

This would be the "Principle of No Surprise" but not PoLS ;-)

> (it could also be promoted as good style for all Ruby programs and libraries
> that make methods available. For example:
> Every method without a '!' makes a copy,
> every method with a '!' is destructive.
> Every method that is to be used by others
> (in public classes, libraries, etc.) should consist of both versions.)

There are many methods, that do not modify the object; should then for each method
a "!" version? There are two many methods, where this doesn't make any sense (most 
libraries other than datatypes).

  class Sensor

    def getTemparature
      @temperature 
    end

    def setTemparature(x)
      @temperature = x
    end

  end

Method "setTemperature" is destuctive, should it return a modified copy? 
Or would you call "setTemperature!" instead ?
Would you use Array#pop! instead of Array#pop?


> One possible concept:
> 
> (current, and stringent)
> 1. Variable assignment ist just that; nothing gets copied.
> 1.1. Use dup or clone to get a copy, and assign that.
> 
> (possible:)
> 2. Every method returns a (possibly modified) copy of what it
> worked with.
> 2.2. Every method has a version that doesn't make a copy,
> but directly works with the original.
> 
> Or:
> (possible:)
> 2. Every method works directly with the original.
> 2.2. If you don't want to modify the original,
> use dup or clone to get a copy and pass that.
> 
> Naming conventions like:
> map, copy_and_map
> or
> map_original, map
> or even
> map_original, copy_and_map
> are semantically rich, but too long.
> 
> So perhaps:
> 

map, map!


I am sure, the longer you work with Ruby the more you'll 
like the method names as they are.


Regards,

  Michael

-- 
Michael Neumann
merlin.zwo InfoDesign GmbH
http://www.merlin-zwo.de