From: Tobias Reif Date: 2001-09-04T06:53:43+09:00 Subject: [ruby-talk:20817] Re: RCR: non-bang equivalent to []= 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. It would be OK if all methods are bang by default, and have some version which is non-bang. 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. "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. (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.) 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: 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. The name of this version is always the method name with an appended "!". or: 2. Every method works directly with the original. 2.2. Every method has a version that makes a copy. (Except where it's nonsenese: #max, #first, #last (thanks David Black)) If you don't want to modify the original, use dup or clone to get a copy and pass that; or use the version of the method which returns a copy, which declares that by having '_c' appended to it's name: map_c Tobi -- Tobias Reif http://www.pinkjuice.com/myDigitalProfile.xhtml go_to('www.ruby-lang.org').get(ruby).play.create.have_fun http://www.pinkjuice.com/ruby/