[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

Ruby problem with conditional ranges

Todd A. Jacobs

6/4/2007 6:57:00 AM

I'm running into a problem doing a conditional range in ruby. The sample
code is:

#!/usr/bin/ruby

## one
## two
## three
## four
## five

File.open($0, 'r') { |f|
while f.gets
print $_.sub(/^##/, '') if /^## two/ .. /^## four/
end
}

I'm expecting:

two
three
four

but I get the whole file with the leading pound signs stripped off.
What's wrong here?

--
"Oh, look: rocks!"
-- Doctor Who, "Destiny of the Daleks"

6 Answers

Nobuyoshi Nakada

6/4/2007 7:19:00 AM

0

Hi,

At Mon, 4 Jun 2007 15:56:31 +0900,
Todd A. Jacobs wrote in [ruby-talk:254228]:
> print $_.sub(/^##/, '') if /^## two/ .. /^## four/

print $_.sub(/^##/, '') if ~/^## two/ .. ~/^## four/

> but I get the whole file with the leading pound signs stripped off.
> What's wrong here?

Because Range object isn't nil nor false, and you'd see a
warning if you run with -w option.

warning: range literal in condition

--
Nobu Nakada

come

6/4/2007 7:31:00 AM

0

Hi,

Implicit match against "$_" is not anymore supported in version 1.8.
You cas still use it in command line form (with "-e" option).

In regular file, you have to write the match explicitly :

## one
## two
## three
## four
## five
File.open($0, 'r') { |f|
while f.gets
print $_.sub(/^##/, '') if ($_ =~ /^## two/) .. ($_ =~ /^## four/)
end
}


On 4 juin, 08:56, "Todd A. Jacobs" <tjacobs-sndr-019...@codegnome.org>
wrote:
> I'm running into a problem doing a conditional range in ruby. The sample
> code is:
>
> #!/usr/bin/ruby
>
> ## one
> ## two
> ## three
> ## four
> ## five
>
> File.open($0, 'r') { |f|
> while f.gets
> print $_.sub(/^##/, '') if /^## two/ .. /^## four/
> end
> }
>
> I'm expecting:
>
> two
> three
> four
>
> but I get the whole file with the leading pound signs stripped off.
> What's wrong here?
>
> --
> "Oh, look: rocks!"
> -- Doctor Who, "Destiny of the Daleks"


Todd A. Jacobs

6/5/2007 12:51:00 AM

0

On Mon, Jun 04, 2007 at 04:35:25PM +0900, come wrote:

> Implicit match against "$_" is not anymore supported in version 1.8.

Thanks. Your explanation was very helpful. It works better now, but the
range operator *still* catches more than it should. For example:

#!/usr/bin/ruby -w

## one
## two
## three
## four
## five

File.open($0) do |file|
while file.gets
print $_.sub(/^## /, '') if
($_ =~ /^## two/)...($_ =~ /^## four/)
end
end

prints up to "four" when (as I understand it) it should stop at "three"
since "## four" would make the if-statement false. Am I still missing
something obvious?

--
"Oh, look: rocks!"
-- Doctor Who, "Destiny of the Daleks"

gga

6/5/2007 4:54:00 AM

0

On Jun 4, 9:51 pm, "Todd A. Jacobs" <tjacobs-
sndr-019...@codegnome.org> wrote:
> On Mon, Jun 04, 2007 at 04:35:25PM +0900, come wrote:
>
> prints up to "four" when (as I understand it) it should stop at "three"
> since "## four" would make the if-statement false. Am I still missing
> something obvious?
>

Yes. That will never work, as this is not Perl nor are you creating a
range of regexp (which cannot be done, btw).
See what happens when the match does happen as you want:

irb> a = 'four'
irb> (a =~ /two/)...(a =~ /four/)
ArgumentError: bad value for range

[result is: (nil...'four') ]

Plus the uncommented # in the regex are probably making ruby assume a
comment.

This is another way of writing what you want to do:

#!/usr/bin/ruby -w

## one
## two
## three
## four
## five


File.open($0) do |file|
range = [ '$_ =~ /^## two/', '$_ !~ /^## four/' ]
while file.gets
if eval("#{range[0]}")
print $_.sub(/^## /, '');
range.shift
end
end
end

gga

6/5/2007 5:06:00 AM

0



Sorry. Buggy code posted. Here's a correct implementation.

#!/usr/bin/ruby -w

## one
## two
## three
## five
## six
## four
## five


File.open($0) do |file|
while file.gets
if $_ =~ /^## two/
loop {
print $_.sub(/^## /, '')
file.gets
break if not $_ or $_ =~ /^## four/
}
end
end
end

come

6/5/2007 7:31:00 AM

0

Yes, because (as with Perl) there are two forms of conditional range:
".." and "...".

The three dots form evaluate the condition after the code. Therefore,
the "four" is printed, then the condition is evaluated to false.

The two dots form evaluates the condition before the code. So it
should works as you expect : "($_ =~ /^## two/)..($_ =~ /^## four/)".

On 5 juin, 02:51, "Todd A. Jacobs"

> range operator *still* catches more than it should. For example:
>
> #!/usr/bin/ruby -w
>
> ## one
> ## two
> ## three
> ## four
> ## five
>
> File.open($0) do |file|
> while file.gets
> print $_.sub(/^## /, '') if
> ($_ =~ /^## two/)...($_ =~ /^## four/)
> end
> end
>
> prints up to "four" when (as I understand it) it should stop at "three"
> since "## four" would make the if-statement false. Am I still missing
> something obvious?
>
> --
> "Oh, look: rocks!"
> -- Doctor Who, "Destiny of the Daleks"