String#ggsub

G

Gavin Kistner

I occasionally find myself with gsub regexp that either eat too much,
or work within a nesting, such that I need to run gsub more than once
in order to get the desired end result. The code I end up writing
tends to be of the form:

while foo.gsub!( /.../, ... ); end

Frankly, I really don't like that. It's like JS people who write
things like:
for ( var walkerNode = this; walkerNode.parent; walkerNode =
walkerNode.parent ){}
'abusing' the for loop construct to hold their logic.

Is there some other form in Ruby of "keep doing this until it returns
nil" that is less...gross?
 
S

Simon Kröger

Gavin said:
I occasionally find myself with gsub regexp that either eat too much,
or work within a nesting, such that I need to run gsub more than once
in order to get the desired end result. The code I end up writing tends
to be of the form:

while foo.gsub!( /.../, ... ); end

Frankly, I really don't like that. It's like JS people who write things
like:
for ( var walkerNode = this; walkerNode.parent; walkerNode =
walkerNode.parent ){}
'abusing' the for loop construct to hold their logic.

Is there some other form in Ruby of "keep doing this until it returns
nil" that is less...gross?

loop{break if foo.gsub!( /.../, ... ).nil?}

?

its more explicit and avoids the empty body, but ....
i don't like it either :)

cheers

Simon
 
L

Logan Capaldo

--Apple-Mail-2--947050097
Content-Transfer-Encoding: 7bit
Content-Type: text/plain;
charset=US-ASCII;
delsp=yes;
format=flowed


I occasionally find myself with gsub regexp that either eat too
much, or work within a nesting, such that I need to run gsub more
than once in order to get the desired end result. The code I end up
writing tends to be of the form:

while foo.gsub!( /.../, ... ); end

I'm kinda curious, can we see an example of a regex where this was
necessary?
--Apple-Mail-2--947050097--
 
J

James Edward Gray II

I occasionally find myself with gsub regexp that either eat too
much, or work within a nesting, such that I need to run gsub more
than once in order to get the desired end result. The code I end up
writing tends to be of the form:

while foo.gsub!( /.../, ... ); end

Frankly, I really don't like that. It's like JS people who write
things like:
for ( var walkerNode = this; walkerNode.parent; walkerNode =
walkerNode.parent ){}
'abusing' the for loop construct to hold their logic.

Is there some other form in Ruby of "keep doing this until it
returns nil" that is less...gross?

Of course, it's trivial to roll one up:

#!/usr/local/bin/ruby -w

module Kernel
def complete
loop { break unless yield }
end
end

if __FILE__ == $0
digits = "3211"
complete { digits.gsub!(/(\d)\1+/) { |d| d[0, 1].to_i + 1 } }
p digits # => "4"
end

__END__

Though I do realize that's not what you asked.

James Edward Gray II
 
G

Gavin Kistner

I'm kinda curious, can we see an example of a regex where this was
necessary?

Here's a pared-down example from this week's ruby quiz:

class Array; def random; self[ rand( self.length ) ]; end; end

class String
def variation
out = self.dup
while out.gsub!( /\(([^())?]+)\)(\?)?/ ){
( $2 && ( rand > 0.5 ) ) ? '' : $1.split( '|' ).random
}; end
out
end
end

q = "(How (much|many)|What) is (the (value|result) of)? 10 + 2?"
10.times{ puts q.variation }
#=> What is the value of 10 + 2?
#=> What is the value of 10 + 2?
#=> How many is 10 + 2?
#=> What is 10 + 2?
#=> What is 10 + 2?
#=> How many is 10 + 2?
#=> What is the value of 10 + 2?
#=> What is 10 + 2?
#=> What is the result of 10 + 2?
#=> What is the result of 10 + 2?
 
Y

YANAGAWA Kazuhisa

In Message-Id: <[email protected]>
Trans said:
Oh better:

foo.gsub!( /.../, ... ) while $~

irb(main):001:0> s = 'foo'
=> "foo"
irb(main):002:0> s =~ /never match/
=> nil
irb(main):003:0> s.gsub!(/\w/, '*') while $~
=> nil
irb(main):004:0> s
=> "foo"

So that's not context free.

I tend to use

true while s.gsub!(/.../, ...)

but probably OP doesn't like that because of extra `true'.
 
D

David A. Black

Hi --

In Message-Id: <[email protected]>


irb(main):001:0> s = 'foo'
=> "foo"
irb(main):002:0> s =~ /never match/
=> nil
irb(main):003:0> s.gsub!(/\w/, '*') while $~
=> nil
irb(main):004:0> s
=> "foo"

So that's not context free.

I tend to use

true while s.gsub!(/.../, ...)

but probably OP doesn't like that because of extra `true'.

If you had reason to save the last match, you could do:

m = $~ while s.gsub!(/.../, ...)

:) Also this would work, but it's probably too verbose:

begin s.gsub!(/\w/,"*") end while $~


David
 
T

Trans

So that's not context free.

Ah, good point. Well,

''=~//; foo.gsub!( /.../, ... ) while $~

But that's more fitting an obsucure code contest :)

T.
 
R

Robert Klemme

Gavin said:
I occasionally find myself with gsub regexp that either eat too much,
or work within a nesting, such that I need to run gsub more than once
in order to get the desired end result. The code I end up writing
tends to be of the form:

while foo.gsub!( /.../, ... ); end

Frankly, I really don't like that. It's like JS people who write
things like:
for ( var walkerNode = this; walkerNode.parent; walkerNode =
walkerNode.parent ){}
'abusing' the for loop construct to hold their logic.

Is there some other form in Ruby of "keep doing this until it returns
nil" that is less...gross?

Another one

1 while foo.gsub!( /.../, ... )

Kind regards

robert
 
T

Trans

How about a helper method

def rep(&blk)
r = yield(&blk) until r.nil?
end

rep { foo.gsub!( /.../, ... ) }

T.
 
D

David A. Black

Hi --

Sorry, just woke up:

def rep
r = yield until r.nil?
end

Or (modeled on some earlier suggestions):

def rep
true until yield.nil?
end

or if false is OK:

def rep
true while yield
end

I love watching Ruby code progressively disappear from the screen (and
still be clear) :)


David
 
R

Robert Klemme

David said:
Hi --



Or (modeled on some earlier suggestions):

def rep
true until yield.nil?
end

or if false is OK:

def rep
true while yield
end

I love watching Ruby code progressively disappear from the screen (and
still be clear) :)

Definitely! Now you arrived at my solution - only you use true instead of
1 (three more characters!). :)

Kind regards

robert
 
Y

YANAGAWA Kazuhisa

In Message-Id: <[email protected]>
Robert Klemme said:
Ooops! I overlooked that one. /me smacks himself So the attribution
should of course go to Yanagawa Kazuhisa (I never know which is the
surname and which the christian name with asian names.).

That's derived from the snippet in some Perl book, something like:

$s = "1234567";
1 while $s =~ s/(\d+)(\d{3})/$1,$2/;
# $s == "1,234,567".

so I don't say it's my own :)
 
G

Gavin Kistner

I tend to use

true while s.gsub!(/.../, ...)

but probably OP doesn't like that because of extra `true'.

Mostly I don't like it for the confusing/vapid nature of true there.
But it makes me think that I sort of like:

:go while s.gsub!( /.../, ... )

or perhaps

while s.gsub!( /.../, ... )
# Keep on truckin'!
end

or perhaps

while s.gsub!( /.../, ... )
:ya_cant_and_ya_wont_and_ya_dont_stop
end

:)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,766
Messages
2,569,569
Members
45,042
Latest member
icassiem

Latest Threads

Top