# RCR 296: Destructive methods return self

**URL:** <https://rubytalk.org/t/rcr-296-destructive-methods-return-self/17043>\
**Category:** ruby-talk\
**Created:** [19 March 2005 21:34 UTC](https://rubytalk.org/t/rcr-296-destructive-methods-return-self/17043 "2005-03-19T21:34:18Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![Daniel\_Amelang](https://avatars.discourse-cdn.com/v4/letter/d/d9b06d/32.png) [@Daniel\_Amelang](https://rubytalk.org/u/Daniel_Amelang)\
**Post date:** [19 March 2005 21:34 UTC](https://rubytalk.org/t/rcr-296-destructive-methods-return-self/17043/1 "2005-03-19T21:34:18Z")

</div>

I know that it's not standard policy to announce RCRs on ruby-talk,  
but since this has been a topic of conversation (debate, polemic,  
death threats?) lately on this list, I thought it relevant.

RCR 296: Destructive methods return self

[http://www.rcrchive.net/rcr/show/296](http://www.rcrchive.net/rcr/show/296)

Let the flame war begin!

Dan

---

<div class="post-metadata">

**Author:** ![David\_A\_Black3](https://avatars.discourse-cdn.com/v4/letter/d/6a8cbe/32.png) [@David\_A\_Black3](https://rubytalk.org/u/David_A_Black3)\
**Post date:** [19 March 2005 21:46 UTC](https://rubytalk.org/t/rcr-296-destructive-methods-return-self/17043/2 "2005-03-19T21:46:15Z")

</div>

Hi --

> I know that it's not standard policy to announce RCRs on ruby-talk,  
> but since this has been a topic of conversation (debate, polemic,  
> death threats?) lately on this list, I thought it relevant.
> 
> RCR 296: Destructive methods return self
> 
> [RCR 296: Destructive methods return self](http://www.rcrchive.net/rcr/show/296)
> 
> Let the flame war begin!

No war on RCRchive, please.... The 150 or so discussions of this  
topic I've been witness to have all been very civil 🙂

By the way, the ruby-talk.org/###### URL syntax doesn't work any more.  
You have to do:  
[http://www.ruby-talk.org/cgi-bin/scat.rb/ruby/ruby-talk/######](http://www.ruby-talk.org/cgi-bin/scat.rb/ruby/ruby-talk/######)

I'll try to fix them directly in the database.

David

> **···**
>
> On Sun, 20 Mar 2005, Daniel Amelang wrote:
> 
> --  
> David A. Black  
> dblack@wobblini.net

---

<div class="post-metadata">

**Author:** ![Anonymous\_Coward](https://avatars.discourse-cdn.com/v4/letter/a/94ad74/32.png) [@Anonymous\_Coward](https://rubytalk.org/u/Anonymous_Coward)\
**Post date:** [19 March 2005 21:46 UTC](https://rubytalk.org/t/rcr-296-destructive-methods-return-self/17043/3 "2005-03-19T21:46:23Z")

</div>

In data 3/19/2005, "Daniel Amelang" \<daniel.amelang@gmail.com\> ha  
scritto:

> I know that it's not standard policy to announce RCRs on ruby-talk,  
> but since this has been a topic of conversation (debate, polemic,  
> death threats?) lately on this list, I thought it relevant.

Wonder what's the difference between  
"I'll kill you" and "I'll kill you!"

> RCR 296: Destructive methods return self
> 
> [RCR 296: Destructive methods return self](http://www.rcrchive.net/rcr/show/296)
> 
> Let the flame war begin!
> 
> Dan

E

---

<div class="post-metadata">

**Author:** ![Daniel\_Amelang](https://avatars.discourse-cdn.com/v4/letter/d/d9b06d/32.png) [@Daniel\_Amelang](https://rubytalk.org/u/Daniel_Amelang)\
**Post date:** [19 March 2005 22:27 UTC](https://rubytalk.org/t/rcr-296-destructive-methods-return-self/17043/4 "2005-03-19T22:27:33Z")

</div>

For those interested in an alternative, I just put this up on the RCR:

Perhaps a more interesting solution would be to get rid of all  
destructive methods and work on optimizing ther existing  
non-destructive counterparts. Matz seems to prefer this solution.

[http://ruby-talk.org/cgi-bin/scat.rb/ruby/ruby-talk/17764](http://ruby-talk.org/cgi-bin/scat.rb/ruby/ruby-talk/17764)

Unfortunately, the non-destructive versions are still quite noticeably slower.

If interest towards this approach materializes, I would be happy to  
supercede this RCR.

Dan

---

<div class="post-metadata">

**Author:** ![David\_A\_Black3](https://avatars.discourse-cdn.com/v4/letter/d/6a8cbe/32.png) [@David\_A\_Black3](https://rubytalk.org/u/David_A_Black3)\
**Post date:** [19 March 2005 21:48 UTC](https://rubytalk.org/t/rcr-296-destructive-methods-return-self/17043/5 "2005-03-19T21:48:56Z")

</div>

Actually you can do this as a minor edit, as the RCRs author. (Silly  
me, I forgot how convenient I made it 🙂

David

> **···**
>
> On Sun, 20 Mar 2005, David A. Black wrote:
> 
> > I'll try to fix them directly in the database.
> 
> --  
> David A. Black  
> dblack@wobblini.net

---

<div class="post-metadata">

**Author:** ![Nikolai\_Weibull](https://avatars.discourse-cdn.com/v4/letter/n/ce7236/32.png) [@Nikolai\_Weibull](https://rubytalk.org/u/Nikolai_Weibull)\
**Post date:** [19 March 2005 22:36 UTC](https://rubytalk.org/t/rcr-296-destructive-methods-return-self/17043/6 "2005-03-19T22:36:30Z")

</div>

\* Daniel Amelang (Mar 19, 2005 23:30):

> Perhaps a more interesting solution would be to get rid of all  
> destructive methods and work on optimizing ther existing  
> non-destructive counterparts. Matz seems to prefer this solution.

> [http://ruby-talk.org/cgi-bin/scat.rb/ruby/ruby-talk/17764](http://ruby-talk.org/cgi-bin/scat.rb/ruby/ruby-talk/17764)

> Unfortunately, the non-destructive versions are still quite noticeably  
> slower.

No they're not. Where are you getting these assertions from?,  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nikolai

> **···**
>
> --  
> ::: name: Nikolai Weibull :: aliases: pcp / lone-star / aka :::  
> ::: born: Chicago, IL USA :: loc atm: Gothenburg, Sweden :::  
> ::: page: minimalistic.org :: fun atm: gf,lps,ruby,lisp,war3 :::  
> main(){printf(&linux["\021%six\012\0"],(linux)["have"]+"fun"-97);}

---

<div class="post-metadata">

**Author:** ![HAL\_9000](https://avatars.discourse-cdn.com/v4/letter/h/90ced4/32.png) [@HAL\_9000](https://rubytalk.org/u/HAL_9000)\
**Post date:** [20 March 2005 01:27 UTC](https://rubytalk.org/t/rcr-296-destructive-methods-return-self/17043/7 "2005-03-20T01:27:09Z")

</div>

David A. Black wrote:

> By the way, the ruby-talk.org/###### URL syntax doesn't work any more.  
> You have to do:  
> [http://www.ruby-talk.org/cgi-bin/scat.rb/ruby/ruby-talk/######](http://www.ruby-talk.org/cgi-bin/scat.rb/ruby/ruby-talk/######)

That's disappointing. I found that feature very convenient.

Who administers the app? Can that function be restored?

Hal

---

<div class="post-metadata">

**Author:** ![Yukihiro\_Matsumoto2](https://avatars.discourse-cdn.com/v4/letter/y/b9e5f3/32.png) [@Yukihiro\_Matsumoto2](https://rubytalk.org/u/Yukihiro_Matsumoto2)\
**Post date:** [22 March 2005 01:19 UTC](https://rubytalk.org/t/rcr-296-destructive-methods-return-self/17043/8 "2005-03-22T01:19:04Z")

</div>

Hi,

> Perhaps a more interesting solution would be to get rid of all  
> destructive methods and work on optimizing ther existing  
> non-destructive counterparts. Matz seems to prefer this solution.

I don't like this proposal, since it loose some feature (modify  
detection) and there's no way to recover without serious performance  
penalty, which makes no sense of bang methods usage.

Alternative plans:

&nbsp;&nbsp;(1) remove bang methods altogether.

&nbsp;&nbsp;(2) current bang methods are bad because they work most of the  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cases, and fail if no change has made. thus let us make bang  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;methods return something other than self, boolean for example,  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;to fail always. this forces no chaining of bang methods.

&nbsp;&nbsp;(3) introduce "real" multiple return values ala common lisp, and let  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;the first returned value as the receiver and the second return  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;value is boolean value to denote success/failure.

&nbsp;&nbsp;(4) add some kind of reference counting, and if the receiver is  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;referenced from only one place, modify the receiver in place, to  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;gain performance.

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;matz.

> **···**
>
> In message "Re: RCR 296: Destructive methods return self" on Sun, 20 Mar 2005 07:27:33 +0900, Daniel Amelang \<daniel.amelang@gmail.com\> writes:

---

<div class="post-metadata">

**Author:** ![Daniel\_Amelang](https://avatars.discourse-cdn.com/v4/letter/d/d9b06d/32.png) [@Daniel\_Amelang](https://rubytalk.org/u/Daniel_Amelang)\
**Post date:** [19 March 2005 22:16 UTC](https://rubytalk.org/t/rcr-296-destructive-methods-return-self/17043/9 "2005-03-19T22:16:16Z")

</div>

Update: the RCR is now 297. Sorry, slip of the hand. I really meant  
'minor edit', I swear!

> **···**
>
> On Sun, 20 Mar 2005 06:48:56 +0900, David A. Black \<dblack@wobblini.net\> wrote:
> 
> > On Sun, 20 Mar 2005, David A. Black wrote:
> > 
> > \> I'll try to fix them directly in the database.
> > 
> > Actually you can do this as a minor edit, as the RCRs author. (Silly  
> > me, I forgot how convenient I made it 🙂
> > 
> > David
> > 
> > --  
> > David A. Black  
> > dblack@wobblini.net

---

<div class="post-metadata">

**Author:** ![Daniel\_Amelang](https://avatars.discourse-cdn.com/v4/letter/d/d9b06d/32.png) [@Daniel\_Amelang](https://rubytalk.org/u/Daniel_Amelang)\
**Post date:** [19 March 2005 22:47 UTC](https://rubytalk.org/t/rcr-296-destructive-methods-return-self/17043/10 "2005-03-19T22:47:32Z")

</div>

> No they're not. Where are you getting these assertions from?,

I use ruby in the bioinformatics field. We deal with very long  
biological sequence data and protein structures. I'll have to go  
through my code and post some examples with corresponding bio data,  
but I've already spent enough time today on the RCR. I may have some  
examples from my computer graphics class years ago that used sort!  
also. You're right for asking for benchmarks, I just have to move on  
to other things right now.

So, anyone else want to brew up some examples? I'd be glad to be proved wrong.

And don't forget, unless bang(!) methods are eliminated entirely,  
there is still the problem with the confusion (of experienced ruby  
programmers).

Dan

---

<div class="post-metadata">

**Author:** ![Daniel\_Berger3](https://avatars.discourse-cdn.com/v4/letter/d/c68b51/32.png) [@Daniel\_Berger3](https://rubytalk.org/u/Daniel_Berger3)\
**Post date:** [19 March 2005 23:59 UTC](https://rubytalk.org/t/rcr-296-destructive-methods-return-self/17043/11 "2005-03-19T23:59:54Z")

</div>

Nikolai Weibull wrote:

> \* Daniel Amelang (Mar 19, 2005 23:30):  
> \> Perhaps a more interesting solution would be to get rid of all  
> \> destructive methods and work on optimizing ther existing  
> \> non-destructive counterparts. Matz seems to prefer this solution.
> 
> \> [http://ruby-talk.org/cgi-bin/scat.rb/ruby/ruby-talk/17764](http://ruby-talk.org/cgi-bin/scat.rb/ruby/ruby-talk/17764)
> 
> \> Unfortunately, the non-destructive versions are still quite

noticeably

> \> slower.
> 
> No they're not. Where are you getting these assertions from?,  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nikolai

Oh, I dunno. Maybe this benchmark?

The only exception was slice vs. slice!. No idea what happened there.

Here are the results of my benchmark running on a 1.8 GHz P4, 512MB  
RAM, on Windows XP, SP2. The actual benchmark code I used it further  
below.

C:\eclipse\workspace\ruby-foo\benchmarks\>ruby bang.rb  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;user system total real  
capitalize 1.862000 0.000000 1.862000 ( 1.923000)  
capitalize! 0.591000 0.000000 0.591000 ( 0.600000)  
chomp 1.663000 0.010000 1.673000 ( 1.853000)  
chomp! 0.510000 0.000000 0.510000 ( 0.511000)  
delete 5.739000 0.030000 5.769000 ( 6.449000)  
delete! 4.396000 0.000000 4.396000 ( 4.606000)  
downcase 1.712000 0.010000 1.722000 ( 2.294000)  
downcase! 0.581000 0.000000 0.581000 ( 0.580000)  
gsub 4.296000 0.030000 4.326000 ( 5.188000)  
gsub! 0.972000 0.000000 0.972000 ( 1.161000)  
lstrip 1.762000 0.020000 1.782000 ( 2.123000)  
lstrip! 0.431000 0.000000 0.431000 ( 0.431000)  
next 1.813000 0.000000 1.813000 ( 1.933000)  
next! 1.331000 0.010000 1.341000 ( 1.472000)  
reverse 1.633000 0.010000 1.643000 ( 1.742000)  
reverse! 0.380000 0.000000 0.380000 ( 0.501000)  
rstrip 1.773000 0.000000 1.773000 ( 1.882000)  
rstrip! 0.420000 0.000000 0.420000 ( 0.431000)  
slice 1.883000 0.020000 1.903000 ( 2.454000)  
slice! 3.415000 0.010000 3.425000 ( 3.765000)  
strip 1.793000 0.000000 1.793000 ( 1.812000)  
strip! 0.370000 0.000000 0.370000 ( 0.411000)  
sub 1.302000 0.000000 1.302000 ( 1.382000)  
sub! 0.901000 0.000000 0.901000 ( 1.202000)  
swapcase 0.862000 0.000000 0.862000 ( 0.961000)  
swapcase! 0.420000 0.000000 0.420000 ( 0.451000)  
tr 3.515000 0.000000 3.515000 ( 3.925000)  
tr 2.284000 0.000000 2.284000 ( 2.484000)  
tr\_s 3.545000 0.010000 3.555000 ( 3.845000)  
tr\_s! 2.193000 0.000000 2.193000 ( 2.303000)  
upcase 2.023000 0.000000 2.023000 ( 2.103000)  
upcase! 0.631000 0.000000 0.631000 ( 0.651000)

require "benchmark"  
include Benchmark

s1 = " hello "  
s2 = " hello "  
s3 = " hello "  
max = 500000

bm do |bench|  
&nbsp;&nbsp;&nbsp;bench.report("capitalize"){  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;max.times{ s1.capitalize }  
&nbsp;&nbsp;&nbsp;}

&nbsp;&nbsp;&nbsp;bench.report("capitalize!"){  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;max.times{ s1.capitalize! }  
&nbsp;&nbsp;&nbsp;}

&nbsp;&nbsp;&nbsp;bench.report("chomp"){  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;max.times{ s1.chomp }  
&nbsp;&nbsp;&nbsp;}

&nbsp;&nbsp;&nbsp;bench.report("chomp!"){  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;max.times{ s1.chomp! }  
&nbsp;&nbsp;&nbsp;}

&nbsp;&nbsp;&nbsp;bench.report("delete"){  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;max.times{ s1.delete("o") }  
&nbsp;&nbsp;&nbsp;}

&nbsp;&nbsp;&nbsp;bench.report("delete!"){  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;max.times{ s1.delete!("o") }  
&nbsp;&nbsp;&nbsp;}

&nbsp;&nbsp;&nbsp;bench.report("downcase"){  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;max.times{ s1.downcase }  
&nbsp;&nbsp;&nbsp;}

&nbsp;&nbsp;&nbsp;bench.report("downcase!"){  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;max.times{ s1.downcase! }  
&nbsp;&nbsp;&nbsp;}

&nbsp;&nbsp;&nbsp;bench.report("gsub"){  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;max.times{ s1.gsub(/e/,"i") }  
&nbsp;&nbsp;&nbsp;}

&nbsp;&nbsp;&nbsp;bench.report("gsub!"){  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;max.times{ s1.gsub!(/e/,"i") }  
&nbsp;&nbsp;&nbsp;}

&nbsp;&nbsp;&nbsp;bench.report("lstrip"){  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;max.times{ s1.lstrip }  
&nbsp;&nbsp;&nbsp;}

&nbsp;&nbsp;&nbsp;bench.report("lstrip!"){  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;max.times{ s1.lstrip! }  
&nbsp;&nbsp;&nbsp;}

&nbsp;&nbsp;&nbsp;bench.report("next"){  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;max.times{ s1.next }  
&nbsp;&nbsp;&nbsp;}

&nbsp;&nbsp;&nbsp;bench.report("next!"){  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;max.times{ s1.next! }  
&nbsp;&nbsp;&nbsp;}

&nbsp;&nbsp;&nbsp;bench.report("reverse"){  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;max.times{ s1.reverse }  
&nbsp;&nbsp;&nbsp;}

&nbsp;&nbsp;&nbsp;bench.report("reverse!"){  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;max.times{ s1.reverse! }  
&nbsp;&nbsp;&nbsp;}

&nbsp;&nbsp;&nbsp;bench.report("rstrip"){  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;max.times{ s1.rstrip }  
&nbsp;&nbsp;&nbsp;}

&nbsp;&nbsp;&nbsp;bench.report("rstrip!"){  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;max.times{ s1.rstrip! }  
&nbsp;&nbsp;&nbsp;}

&nbsp;&nbsp;&nbsp;bench.report("slice"){  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;max.times{ s2.slice(1..4) }  
&nbsp;&nbsp;&nbsp;}

&nbsp;&nbsp;&nbsp;bench.report("slice!"){  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;max.times{ s2.slice!(1..4) }  
&nbsp;&nbsp;&nbsp;}

&nbsp;&nbsp;&nbsp;bench.report("strip"){  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;max.times{ s2.strip }  
&nbsp;&nbsp;&nbsp;}

&nbsp;&nbsp;&nbsp;bench.report("strip!"){  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;max.times{ s2.strip! }  
&nbsp;&nbsp;&nbsp;}

&nbsp;&nbsp;&nbsp;bench.report("sub"){  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;max.times{ s2.sub(/e/,"i") }  
&nbsp;&nbsp;&nbsp;}

&nbsp;&nbsp;&nbsp;bench.report("sub!"){  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;max.times{ s2.sub!(/e/,"i") }  
&nbsp;&nbsp;&nbsp;}

&nbsp;&nbsp;&nbsp;bench.report("swapcase"){  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;max.times{ s2.swapcase }  
&nbsp;&nbsp;&nbsp;}

&nbsp;&nbsp;&nbsp;bench.report("swapcase!"){  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;max.times{ s2.swapcase! }  
&nbsp;&nbsp;&nbsp;}

&nbsp;&nbsp;&nbsp;bench.report("tr"){  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;max.times{ s3.tr("e","a") }  
&nbsp;&nbsp;&nbsp;}

&nbsp;&nbsp;&nbsp;bench.report("tr"){  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;max.times{ s3.tr!("e","a") }  
&nbsp;&nbsp;&nbsp;}

&nbsp;&nbsp;&nbsp;bench.report("tr\_s"){  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;max.times{ s3.tr\_s("a","e") }  
&nbsp;&nbsp;&nbsp;}

&nbsp;&nbsp;&nbsp;bench.report("tr\_s!"){  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;max.times{ s3.tr\_s!("a","e") }  
&nbsp;&nbsp;&nbsp;}

&nbsp;&nbsp;&nbsp;bench.report("upcase"){  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;max.times{ s3.upcase }  
&nbsp;&nbsp;&nbsp;}

&nbsp;&nbsp;&nbsp;bench.report("upcase!"){  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;max.times{ s3.upcase! }  
&nbsp;&nbsp;&nbsp;}  
end

Regards,

Dan

---

<div class="post-metadata">

**Author:** ![Glenn\_Parker1](https://avatars.discourse-cdn.com/v4/letter/g/ba8739/32.png) [@Glenn\_Parker1](https://rubytalk.org/u/Glenn_Parker1)\
**Post date:** [22 March 2005 02:23 UTC](https://rubytalk.org/t/rcr-296-destructive-methods-return-self/17043/12 "2005-03-22T02:23:47Z")

</div>

Yukihiro Matsumoto wrote:

> Alternative plans:
> 
> &nbsp;&nbsp;(1) remove bang methods altogether.

Backwards compatibility is lost.

> &nbsp;&nbsp;(2) current bang methods are bad because they work most of the  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cases, and fail if no change has made. thus let us make bang  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;methods return something other than self, boolean for example,  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;to fail always. this forces no chaining of bang methods.

Tolerable, but only because it removes the element of surprise.

> &nbsp;&nbsp;(3) introduce "real" multiple return values ala common lisp, and let  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;the first returned value as the receiver and the second return  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;value is boolean value to denote success/failure.

Ick. Ever wonder why other languages don't do this?

> &nbsp;&nbsp;(4) add some kind of reference counting, and if the receiver is  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;referenced from only one place, modify the receiver in place, to  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;gain performance.

Oooo, pretty! Seems like it might defeat the goal of optimizing things, unless the reference counting could reduce the overall impact of garbage collection.

When I'm playing with simple algorithms, disabling garbage collection seems to yield a guaranteed 20% speedup, even for relatively short tasks (\< 30 sec.).

Another option:

&nbsp;&nbsp;&nbsp;&nbsp;(5) add alternative destructive methods with different names that  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;always return self.

This is the change with the least impact, but I realize it is ugly.

> **···**
>
> --  
> Glenn Parker | glenn.parker-AT-comcast.net | \<[http://www.tetrafoil.com/&gt](http://www.tetrafoil.com/&gt);

---

<div class="post-metadata">

**Author:** ![Daniel\_Amelang](https://avatars.discourse-cdn.com/v4/letter/d/d9b06d/32.png) [@Daniel\_Amelang](https://rubytalk.org/u/Daniel_Amelang)\
**Post date:** [22 March 2005 02:31 UTC](https://rubytalk.org/t/rcr-296-destructive-methods-return-self/17043/13 "2005-03-22T02:31:08Z")

</div>

Yes, I am liking the proposal less and less as time goes on. And I'm  
the one who wrote it!

I'm \*am\* liking the (1) remove bang methods altogether idea more and  
more. It has the positive (minor) side effect of reducing the number  
of instance methods for String and Array, which is nice. And of  
course, it eliminates the chaining confusion, since bang methods are  
no longer an option. Losing the bang methods has also proven to be  
only a minor loss in the efficiency category (we could live without  
them).

But, this alone doesn't solve the problem with the modification  
detection. Is it \_that\_ common? I've heard only one person complain so  
far. Yet, you (matz) seem to be concerned about losing that  
functionality, so I'll be concerned too. 🙂

Will (2) really solve the problem, or just mitigate it slightly?

(3) is an interesting solution to the detection problem. Perhaps  
having real multiple return values will solve some other issues in  
Rubyland also (anyone?). Using a modified version of the 'strip'  
method, let me illustrate a minor modification in the language that  
allows for easier use of multiple return values:

class String  
&nbsp;&nbsp;# The new strip returns both the string result and  
&nbsp;&nbsp;# a flag that some change occured.  
&nbsp;&nbsp;def strip  
&nbsp;&nbsp;&nbsp;&nbsp;...  
&nbsp;&nbsp;&nbsp;&nbsp;return result, changed  
&nbsp;&nbsp;end  
end

# This works now:  
str, changed = "hello ".strip

# But currently, when you only want the string result, you have to do this:  
str, \_ = "hello ".strip

# Because this:  
str = "hello ".strip

# gives you an array ☹

# Why not make the minor change such that this:  
\*str = "hello ".strip

# gives you the array and this:

str = "hello ".strip

only gives you the \_first\_ of the multiple return values. That way we can return  
multiple return values without requiring the receivers to use \_ all the time  
to throw away the rest.

I'm done. Thanks for taking the time to consider my proposal.

Dan

---

<div class="post-metadata">

**Author:** ![HAL\_9000](https://avatars.discourse-cdn.com/v4/letter/h/90ced4/32.png) [@HAL\_9000](https://rubytalk.org/u/HAL_9000)\
**Post date:** [22 March 2005 06:12 UTC](https://rubytalk.org/t/rcr-296-destructive-methods-return-self/17043/14 "2005-03-22T06:12:52Z")

</div>

Obviously I'm only expressing my opinion here, which often  
is nearly worthless:

Yukihiro Matsumoto wrote:

> Alternative plans:
> 
> &nbsp;&nbsp;(1) remove bang methods altogether.

"The cradle is too short. Let's cut off the baby's feet."

> &nbsp;&nbsp;(2) current bang methods are bad because they work most of the  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cases, and fail if no change has made. thus let us make bang  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;methods return something other than self, boolean for example,  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;to fail always. this forces no chaining of bang methods.

Again, please no. I like chaining.

> &nbsp;&nbsp;(3) introduce "real" multiple return values ala common lisp, and let  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;the first returned value as the receiver and the second return  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;value is boolean value to denote success/failure.

Interesting, but only if "the common case is the prettier one" and  
back compatibility is maintained. I don't want to go sprinkling  
commas and asterisks through old code.

> &nbsp;&nbsp;(4) add some kind of reference counting, and if the receiver is  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;referenced from only one place, modify the receiver in place, to  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;gain performance.

Hmm, does this work? Would there be times it would not be obvious whether we  
were changing the original object or not? If so, unacceptable.

I would almost suggest what I once suggested as a joke: Combine the ! and ?  
suffixes.

&nbsp;&nbsp;&nbsp;&nbsp;gsub! returns self  
&nbsp;&nbsp;&nbsp;&nbsp;gsub!? returns self or nil (yes, it looks silly)

Or alternatively:

&nbsp;&nbsp;&nbsp;&nbsp;gsub! returns self or nil as now  
&nbsp;&nbsp;&nbsp;&nbsp;gsub\_! returns self (yes, it's ugly)

Or perhaps:

&nbsp;&nbsp;&nbsp;&nbsp;Give the objects a "changed?" flag. Every bang method is expected to  
&nbsp;&nbsp;&nbsp;&nbsp;set it...

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;obj.gsub!(...) # returns self and sets flag  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if obj.changed? then... # not thread-friendly, but I could live with it

&nbsp;&nbsp;&nbsp;&nbsp;Is that really an expensive solution?

Hal

---

<div class="post-metadata">

**Author:** ![Ben\_Giddings1](https://avatars.discourse-cdn.com/v4/letter/b/779978/32.png) [@Ben\_Giddings1](https://rubytalk.org/u/Ben_Giddings1)\
**Post date:** [22 March 2005 17:21 UTC](https://rubytalk.org/t/rcr-296-destructive-methods-return-self/17043/15 "2005-03-22T17:21:11Z")

</div>

Yukihiro Matsumoto wrote:

> &nbsp;&nbsp;(2) current bang methods are bad because they work most of the  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cases, and fail if no change has made. thus let us make bang  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;methods return something other than self, boolean for example,  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;to fail always. this forces no chaining of bang methods.

I think this one is the most consistent way of doing things. In a way, using chaining with receiver-modifying methods doesn't make sense. You really don't want to modify the return value of the method, you want to modify the original object. I think the main reaon people want to chain bang methods is that they don't like having to type the variable a lot of times.

the\_config\_string\_for\_foo = $stdin.gets  
the\_config\_string\_for\_foo.strip!.downcase!

is easier to type than

the\_config\_string\_for\_foo = $stdin.gets  
the\_config\_string\_for\_foo.strip!  
the\_config\_string\_for\_foo.downcase!

But it seems to me that what people are really looking for is a way to apply multiple methods to an object without having to retype it's name:

the\_config\_string\_for\_foo = $stdin.gets  
the\_config\_string\_for\_foo.apply { strip!; downcase! }

This has been proposed a few times, I think. I can't remember how you (Matz) felt about it. Is the reason Ruby doesn't have a way to do it because you don't like the idea, or you were hoping for consensus on the exact method of doing it?

> &nbsp;&nbsp;(4) add some kind of reference counting, and if the receiver is  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;referenced from only one place, modify the receiver in place, to  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;gain performance.

This sounds like "more work for Matz", but also a really good solution. Most of the time people only want bang methods for efficiency. If that weren't an issue then it would be even easier to have the bang-methods return boolean (modified / not modified) and then people could choose the method based on what they were after (chaining vs. "was something changed") and not based on efficiency.

Ben

---

<div class="post-metadata">

**Author:** ![David\_A\_Black3](https://avatars.discourse-cdn.com/v4/letter/d/6a8cbe/32.png) [@David\_A\_Black3](https://rubytalk.org/u/David_A_Black3)\
**Post date:** [19 March 2005 23:11 UTC](https://rubytalk.org/t/rcr-296-destructive-methods-return-self/17043/16 "2005-03-19T23:11:29Z")

</div>

Hi --

> **···**
>
> On Sun, 20 Mar 2005, Daniel Amelang wrote:
> 
> > Update: the RCR is now 297. Sorry, slip of the hand. I really meant  
> > 'minor edit', I swear!
> 
> I manually fixed it -- it's 296 again 🙂 (with the comments and  
> votes from 297).
> 
> David
> 
> --  
> David A. Black  
> dblack@wobblini.net

---

<div class="post-metadata">

**Author:** ![Nikolai\_Weibull](https://avatars.discourse-cdn.com/v4/letter/n/ce7236/32.png) [@Nikolai\_Weibull](https://rubytalk.org/u/Nikolai_Weibull)\
**Post date:** [20 March 2005 01:11 UTC](https://rubytalk.org/t/rcr-296-destructive-methods-return-self/17043/17 "2005-03-20T01:11:43Z")

</div>

\* Daniel Berger (Mar 20, 2005 01:10):

> \> \> Unfortunately, the non-destructive versions are still quite  
> \> \> noticeably slower.

> \> No they're not. Where are you getting these assertions from?,

> Oh, I dunno. Maybe this benchmark?

> The only exception was slice vs. slice!. No idea what happened there.

Well, with slice!, you have to do more work than doing a slice. The  
reason is that you have to paste together the parts that are still a  
part of the string. With slice you simply return the substring.

For me, next! is also slower than next.

A comment on your benchmark: doesn't it make more sense to do the tests  
on new strings each time? The benchmark should surely be try to  
evaluate the merit of returning a new string versus replacing its  
contents, right? With a benchmark that preallocates 'max' copies of  
's1' and fetches them from an array for each of the calls to the  
respective functions, the times are much more evenly matched:

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;user system total real  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;capitalize 0.660000 0.000000 0.660000 ( 0.675759)  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;capitalize! 0.480000 0.010000 0.490000 ( 0.494108)  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;chomp 0.660000 0.000000 0.660000 ( 0.680509)  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;chomp! 0.370000 0.000000 0.370000 ( 0.370647)  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;delete 1.300000 0.000000 1.300000 ( 1.296738)  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;delete! 1.070000 0.000000 1.070000 ( 1.068162)  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;downcase 0.630000 0.000000 0.630000 ( 0.639248)  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;downcase! 0.400000 0.000000 0.400000 ( 0.399627)  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;gsub 2.710000 0.020000 2.730000 ( 2.844503)  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;gsub! 2.250000 0.030000 2.280000 ( 2.331406)  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;lstrip 0.700000 0.000000 0.700000 ( 0.705452)  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;lstrip! 0.430000 0.000000 0.430000 ( 0.424257)  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;next 0.570000 0.000000 0.570000 ( 0.570100)  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;next! 0.720000 0.000000 0.720000 ( 0.725646)  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;slice 0.850000 0.000000 0.850000 ( 0.844139)  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;slice! 1.210000 0.000000 1.210000 ( 1.217413)  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;reverse 0.510000 0.000000 0.510000 ( 0.514665)  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;reverse! 0.350000 0.000000 0.350000 ( 0.349400)  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;rstrip 0.660000 0.000000 0.660000 ( 0.664235)  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;rstrip! 0.370000 0.000000 0.370000 ( 0.371327)  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;strip 0.550000 0.000000 0.550000 ( 0.547162)  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;strip! 0.390000 0.000000 0.390000 ( 0.390382)  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sub 0.940000 0.000000 0.940000 ( 0.938963)  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sub! 0.690000 0.000000 0.690000 ( 0.690106)  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;swapcase 0.630000 0.000000 0.630000 ( 0.630045)  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;swapcase! 0.390000 0.000000 0.390000 ( 0.392977)  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;tr 0.850000 0.000000 0.850000 ( 0.852794)  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;tr 0.750000 0.000000 0.750000 ( 0.751016)  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;tr\_s 0.850000 0.000000 0.850000 ( 0.845268)  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;tr\_s! 0.690000 0.000000 0.690000 ( 0.690721)  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;upcase 0.600000 0.000000 0.600000 ( 0.606707)  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;upcase! 0.390000 0.000000 0.390000 ( 0.413688)

Anyway, if you don't like this test, here are the times on my machine  
(it seems Ruby on a Linux system runs a lot faster than on a Windows  
system, and much more evenly between the two versions of each method):

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;user system total real  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;capitalize 0.490000 0.000000 0.490000 ( 0.488138)  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;capitalize! 0.290000 0.000000 0.290000 ( 0.286009)  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;chomp 0.460000 0.000000 0.460000 ( 0.466617)  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;chomp! 0.220000 0.000000 0.220000 ( 0.219798)  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;delete 1.150000 0.000000 1.150000 ( 1.153041)  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;delete! 0.920000 0.000000 0.920000 ( 0.912380)  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;downcase 0.490000 0.000000 0.490000 ( 0.489456)  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;downcase! 0.240000 0.000000 0.240000 ( 0.240895)  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;gsub 1.250000 0.000000 1.250000 ( 1.254223)  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;gsub! 0.520000 0.000000 0.520000 ( 0.516004)  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;lstrip 0.480000 0.000000 0.480000 ( 0.485036)  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;lstrip! 0.200000 0.000000 0.200000 ( 0.198516)  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;next 0.410000 0.000000 0.410000 ( 0.406751)  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;next! 0.430000 0.000000 0.430000 ( 0.430365)  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;reverse 0.380000 0.000000 0.380000 ( 0.384075)  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;reverse! 0.190000 0.000000 0.190000 ( 0.193044)  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;rstrip 0.470000 0.000000 0.470000 ( 0.471682)  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;rstrip! 0.200000 0.000000 0.200000 ( 0.194479)  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;slice 0.600000 0.000000 0.600000 ( 0.596786)  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;slice! 0.960000 0.000000 0.960000 ( 0.961636)  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;strip 0.470000 0.000000 0.470000 ( 0.469545)  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;strip! 0.180000 0.000000 0.180000 ( 0.185437)  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sub 0.620000 0.000000 0.620000 ( 0.620524)  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sub! 0.470000 0.000000 0.470000 ( 0.464609)  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;swapcase 0.380000 0.000000 0.380000 ( 0.380528)  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;swapcase! 0.190000 0.000000 0.190000 ( 0.192872)  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;tr 0.810000 0.000000 0.810000 ( 0.818261)  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;tr 0.590000 0.000000 0.590000 ( 0.615229)  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;tr\_s 0.850000 0.000000 0.850000 ( 0.858405)  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;tr\_s! 0.590000 0.000000 0.590000 ( 0.597201)  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;upcase 0.550000 0.000000 0.550000 ( 0.578785)  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;upcase! 0.250000 0.000000 0.250000 ( 0.252732)

I'm not arguing with the fact that for most methods, the destructive  
version will be faster. I'm just saying that the performance difference  
between the two isn't that big,  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nikolai

> **···**
>
> --  
> ::: name: Nikolai Weibull :: aliases: pcp / lone-star / aka :::  
> ::: born: Chicago, IL USA :: loc atm: Gothenburg, Sweden :::  
> ::: page: minimalistic.org :: fun atm: gf,lps,ruby,lisp,war3 :::  
> main(){printf(&linux["\021%six\012\0"],(linux)["have"]+"fun"-97);}

---

<div class="post-metadata">

**Author:** ![Nikolai\_Weibull](https://avatars.discourse-cdn.com/v4/letter/n/ce7236/32.png) [@Nikolai\_Weibull](https://rubytalk.org/u/Nikolai_Weibull)\
**Post date:** [20 March 2005 01:13 UTC](https://rubytalk.org/t/rcr-296-destructive-methods-return-self/17043/18 "2005-03-20T01:13:55Z")

</div>

\* Daniel Amelang (Mar 19, 2005 23:50):

> I use ruby in the bioinformatics field. We deal with very long  
> biological sequence data and protein structures.

How long? Are you sure String is the class for you? Is it possible  
that some domain-specific data structures would suite your tasks better?  
I'm being curious, not provocative,  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nikolai

> **···**
>
> --  
> ::: name: Nikolai Weibull :: aliases: pcp / lone-star / aka :::  
> ::: born: Chicago, IL USA :: loc atm: Gothenburg, Sweden :::  
> ::: page: minimalistic.org :: fun atm: gf,lps,ruby,lisp,war3 :::  
> main(){printf(&linux["\021%six\012\0"],(linux)["have"]+"fun"-97);}

---

<div class="post-metadata">

**Author:** ![David\_A\_Black3](https://avatars.discourse-cdn.com/v4/letter/d/6a8cbe/32.png) [@David\_A\_Black3](https://rubytalk.org/u/David_A_Black3)\
**Post date:** [22 March 2005 02:56 UTC](https://rubytalk.org/t/rcr-296-destructive-methods-return-self/17043/19 "2005-03-22T02:56:44Z")

</div>

Hi --

> (3) is an interesting solution to the detection problem. Perhaps  
> having real multiple return values will solve some other issues in  
> Rubyland also (anyone?). Using a modified version of the 'strip'  
> method, let me illustrate a minor modification in the language that  
> allows for easier use of multiple return values:
> 
> class String  
> # The new strip returns both the string result and  
> # a flag that some change occured.  
> def strip  
> &nbsp;&nbsp;&nbsp;...  
> &nbsp;&nbsp;&nbsp;return result, changed  
> end  
> end
> 
> # This works now:  
> str, changed = "hello ".strip
> 
> # But currently, when you only want the string result, you have to do this:  
> str, \_ = "hello ".strip
> 
> # Because this:  
> str = "hello ".strip
> 
> # gives you an array ☹

Actually you can just do:

&nbsp;&nbsp;&nbsp;str, = "hello ".strip

to assign the first array element to str. That's a nice construct,  
but it would extremely annoying and feels kind of ad hoc to require it  
for every strip operation (not to mention sub, gsub, reverse, etc.)

Maybe we need StripData, SubData, etc., like MatchData... (No, not  
really 🙂

David

> **···**
>
> On Tue, 22 Mar 2005, Daniel Amelang wrote:
> 
> --  
> David A. Black  
> dblack@wobblini.net

---

<div class="post-metadata">

**Author:** ![Navindra\_Umanee](https://avatars.discourse-cdn.com/v4/letter/n/d78d45/32.png) [@Navindra\_Umanee](https://rubytalk.org/u/Navindra_Umanee)\
**Post date:** [22 March 2005 03:52 UTC](https://rubytalk.org/t/rcr-296-destructive-methods-return-self/17043/20 "2005-03-22T03:52:25Z")

</div>

Interesting observation and benchmark! It might be neat to have  
further details on how you are testing this. Or is this measurement  
done on an actual app that you have deployed?

I guess it might make sense for a Ruby app to disable GC and invoke it  
when really necessary in a speed-critical situation.

Cheers,  
Navin.

> **···**
>
> Glenn Parker \<glenn.parker@comcast.net\> wrote:
> 
> > Oooo, pretty! Seems like it might defeat the goal of optimizing things,  
> > unless the reference counting could reduce the overall impact of garbage  
> > collection.
> > 
> > When I'm playing with simple algorithms, disabling garbage collection  
> > seems to yield a guaranteed 20% speedup, even for relatively short tasks  
> > (\< 30 sec.).

[Next page](https://rubytalk.org/t/rcr-296-destructive-methods-return-self/17043.md?page=2)
