From: bbiker Date: 2007-07-24T04:35:01+09:00 Subject: Re: Is there a replacement for sub? On Jul 23, 2:53 pm, "Michael W. Ryder" <_mwry...@worldnet.att.net> wrote: > 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" > >>>>> 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 wrote: > >>>>>> On 7/20/07, Robert Dober 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.- Hide quoted text - > > - Show quoted text - for single substitution you can use subn!(pattern, replacement) since n defaults to 1. Ditto for subn.