bbiker wrote:
> On Jul 22, 10:39 pm, "Michael W. Ryder" <_mwry... / worldnet.att.net>
> wrote:
>> dbl... / wobblini.net wrote:
>>> Hi --
>>> On Sun, 22 Jul 2007, Bernard Kenik wrote:
>>>> ruby-talk-ad... / ruby-lang.org wrote:
>>>>> ------------------------------------------------------------------------
>>>>> Subject:
>>>>> Re: Is there a replacement for sub?
>>>>> From:
>>>>> "Robert Dober" <robert.do... / gmail.com>
>>>>> Date:
>>>>> Fri, 20 Jul 2007 20:49:07 +0900
>>>>> To:
>>>>> ruby-t... / ruby-lang.org (ruby-talk ML)
>>>>> To:
>>>>> ruby-t... / ruby-lang.org (ruby-talk ML)
>>>>> On 7/20/07, Martin DeMello <martindeme... / gmail.com> wrote:
>>>>>> On 7/20/07, Robert Dober <robert.do... / gmail.com> wrote:
>>>>>>> I was reading this whole thread and I kind of think to be dreaming, I
>>>>>>> must have missed something obvious!!!
>>>>>>> Anyway maybe this is was OP wants, well I think it is ;)
>>>>>>> 529/29 > irb
>>>>>>> irb(main):001:0> a='a b c d e f'
>>>>>>> => "a b c d e f"
>>>>>>> irb(main):002:0> a.gsub!(" ","")
>>>>>> Nope, he wants a method that only replaces the first n occurrences of
>>>>>> the pattern. gsub will not do this - you need to run sub in a loop.
>>>>>> (This is where perl's "continue matching where you left off" would
>>>>>> have been a nice optimisation)
>>>> The primary problem is that sub! returns nil when no substitutions are
>>>> made.
>>>> I have similar problem with Array#flatten!, Array#uniq! since it
>>>> causes problem when chaining!
>>>> My solution has been to override these bang! methods to return self
>>>> even when the bang! method did not have to change the receiver.
>>>> for sub! I would override the sub! method as follow
>>>> class String
>>>> alias old_sub!  sub!
>>>> def sub!(pattern, replacement)
>>>>     self.old_sub!(pattern, replacement)
>>>>     self
>>>> end
>>>> end
>>>> As a user of a method, I really do not care if the method did not have
>>>> to do anything so long as the object is in the desired state.
>>>> For an array such as  arr = [1,2,3,4,5,6], I can safely chain the
>>>> bang! methods without worrying about nil returns from flatten! and uniq!
>>>> arr.flatten!.uniq!.sort!    # NO ERROR MSG "undefined method `uniq!'
>>>> for nil:NilClass (NoMethodError)" because flatten! would have returned
>>>> nil
>>>> p arr  =>  [1, 2, 3, 4, 5, 6]
>>> I would very, very strongly advise you, and everyone else, not to do
>>> this.  You will break any code (inside the standard library and/or any
>>> other code you load, or any code that uses your code) that depends on
>>> the documented behavior of these methods.  You may not like how sub!
>>> and friends work, but it's a very bad idea to make the decision to
>>> change them on behalf of everyone else, over and above the language
>>> documentation.
>> What I planned to do was get rid of the alias and change the name of the
>> new sub! method to something like subf! for just that reason.  I still
>> prefer this version much better than the original version as there are
>> no surprises.  It is very hard to change 30+ years of practice overnight.
>>
>>
>>
>>> David- Hide quoted text -
>> - Show quoted text -- Hide quoted text -
>>
>> - Show quoted text -
> 
> Actually you do not have to define subf! as an intermediate step
> you can directly define subn and subn! directly
> 
> class String
>   def subn!(pattern, replacement, n = 1)
>     n.times { self.sub!(pattern, replacement) }
>     self   # or  return self
>   end
> 
>   def subn(pattern, replacement, n = 1)
>     return self if n < 1
>     @str = self.sub(pattern, replacement)
>     (n-1).times { @str = @str.sub(pattern, replacement) }
>     @str      # or return @str
>   end
> end
> 
> Note that sub and sub! are the original definitions
> 
> You use subn(pattern, replacement) and subn!(pattern, replacement) as
> substitutes for sub(pattern, replacement) and sub!(pattern,
> replacement) which eliminate the unpleasant surprises.
> 
> In addition, both can be safely chained !!!!
> 
> Hope this helps
> 

Thanks for the updated code.  I think I will keep the subf and subf! 
definitions for when I want to do single replacements that are free of 
surprises.  Maybe I will someday be able to use the original definitions 
with confidence but when I am in the middle of a programming run I hate 
to stop and look up language definitions to avoid problems.  It just 
ruins the flow of thought.