Newbee Question on what if x === 2..5 does

I’m new to ruby and don’t understand why the following code does what
is does. Can anyone enlighten me?

ruby -e 'a = [1,2,3,4,5,6,7,8,9,10]; a.each { |x| if (x === 2…5 )
then print x, " " end}; puts ’
2 3 4 5 6 7 8 9 10

I would have thought this would be the same as

ruby -e 'a = [1,2,3,4,5,6,7,8,9,10]; a.each { |x| case x; when 2…5
then print x, " "; end}; puts ’
2 3 4 5

I am also confused that

ruby -e ‘while gets; print if /<div id=.*$/ … /</body>/; end’ < fred

UETHUEPUK THEUTEUH teuhepxn thueonhoe ononueuouh

and a three . range test give the same output.

ruby -e ‘while gets; print if /<div id=.*$/ … /</body>/; end’ < fred

UETHUEPUK THEUTEUH teuhepxn thueonhoe ononueuouh

The original file ‘fred’ is

hello
UETHUEPUK THEUTEUH teuhepxn thueonhoe ononueuouh

ruby -v
ruby 1.8.4 (2005-12-24) [powerpc-darwin8.6.0]

Compiled from the distribution, not the Mac OS shipped version.

Rob

Rob B. Ph: +64 (9) 3737 599 Extn 87972
Computing Services Manager Fax: +64 (9) 3737 453
Computer Science Department Mob:+64 (27) 4731 856
The University of Auckland
Rm 391, Level 3
38 Princes Street Robs Home Page
Private bag 92019 http://www.wikarekare.org
Auckland 1001 http://www.burrowes.org

On 5/3/06, Rob B. [email protected] wrote:

then print x, " "; end}; puts ’
2 3 4 5

Try switching x === 2…5 to 2…5 === x. The case equality operator
(===) is not cummutative. The conditions of a case statement are
evaluated using the when condition as the receiver of the case
equality operator, not the argument. Ie.

case a
when b

end

is equivalent to:

if b === a

end

Sorry, can’t help you there. I always have a hard time remembering
what the difference between … and … are in that context. I stay
away from it in favor of more descriptive flagging in a while loop.
E.g.:

flag = false
while line = gets
flag = true if line =~ /<div id=.*$/
flag = false if line =~ /</body>/
print line if flag
end

Jacob F.

I mistyped that (left out an =), but the same result.

rob1:~ rbur004$ ruby -e ‘a = [1,2,3,4,5,6,7,8,9,10]; a.each { |x|
print x, “->”; if (2…5 === x) then print x, " " end; print “\n”}’
1->
2->
3->
4->
5->
6->
7->
8->
9->
10->

On 4/05/2006, at 12:42 PM, Rob B. wrote:

6->

what
2 3 4 5

ruby -e 'while gets; print if /
/; end'

Sorry, can’t help you there. I always have a hard time remembering

38 Princes Street Robs Home Page
Private bag 92019 http://www.wikarekare.org
Auckland 1001 http://www.burrowes.org

Rob

Rob B. Ph: +64 (9) 3737 599 Extn 87972
Computing Services Manager Fax: +64 (9) 3737 453
Computer Science Department Mob:+64 (27) 4731 856
The University of Auckland
Rm 391, Level 3
38 Princes Street Robs Home Page
Private bag 92019 http://www.wikarekare.org
Auckland 1001 http://www.burrowes.org

Hmmm, it works if I bracket the range. Why is that?

rob1:~ rbur004$ ruby -e '[1,2,3,4,5,6,7,8,9,10].each { |x| print x, "-

"; if ((2…5) === x) then print x end; print “\n”}’
1->
2->2
3->3
4->4
5->
6->
7->
8->
9->
10->

On 4/05/2006, at 1:00 PM, Rob B. wrote:

7->

print x, “->”; if (2…5 == x) then print x, " " end; print “\n”}’

2 3 4 5 6 7 8 9 10
equality operator, not the argument. Ie.
end
ononueuouh
teuhepxn
flag = false

Rob

Rob B. Ph: +64 (9) 3737 599 Extn 87972
Computing Services Manager Fax: +64 (9) 3737 453
Computer Science Department Mob:+64 (27) 4731 856
The University of Auckland
Rm 391, Level 3
38 Princes Street Robs Home Page
Private bag 92019 http://www.wikarekare.org
Auckland 1001 http://www.burrowes.org

I get what you mean. It makes sense to have the === as a method of
the range, not of x, but this produces no result at all.

rob1:~ rbur004$ ruby -e ‘a = [1,2,3,4,5,6,7,8,9,10]; a.each { |x|
print x, “->”; if (2…5 == x) then print x, " " end; print “\n”}’
1->
2->
3->
4->
5->
6->
7->
8->
9->
10->

On 4/05/2006, at 11:06 AM, Jacob F. wrote:

ruby -e 'a = [1,2,3,4,5,6,7,8,9,10]; a.each { |x| case x; when 2…5

ruby -e ‘while gets; print if /<div id=.*$/ … /</body>/; end’ <
and a three . range test give the same output.

print line if flag
end

Jacob F.

Rob

Rob B. Ph: +64 (9) 3737 599 Extn 87972
Computing Services Manager Fax: +64 (9) 3737 453
Computer Science Department Mob:+64 (27) 4731 856
The University of Auckland
Rm 391, Level 3
38 Princes Street Robs Home Page
Private bag 92019 http://www.wikarekare.org
Auckland 1001 http://www.burrowes.org

Try using:
if (2…5) === x

the === seems to bind before the …

;D

On May 3, 2006, at 9:13 PM, Rob B. wrote:

Hmmm, it works if I bracket the range. Why is that?

=== has higher precendence than the … operator

2…5 === x is

2…(5 === x)

without parens

On 5/3/06, Rob B. [email protected] wrote:

Hmmm, it works if I bracket the range. Why is that?

I came to the same result as others. I also figured out why you were
getting that weird behavior when using the if statement. Let’s take a
simple test: 3 in 2…5? In irb:

2…5 === 3
ArgumentError: bad value for range

(2…5) === 3
=> true

Looks right, 5 === 3 was binding first, so in the first case we really
had 2…false (since 5 === 3 is false). To verify:

2…false
ArgumentError: bad value for range

So why doesn’t this code:

[1,2,3,4,5,6,7,8,9,10].each do |x|
puts x if 2…5 === x
end

raise that exception? If I use select instead, it “works”:

[1,2,3,4,5,6,7,8,9,10].select{ |x| 2…5 === x }
ArgumentError: bad value for range

The key is the binding again, let’s look at that line with the condition
again:

puts x if 2…5 === x

This is the same as

puts x if 2…(5 === x)

And since the default Object#===, which isn’t overriden by the time we
reach Integer, returns false, we have:

puts x if 2…false

regardless of x. Now, if 2…false meant a range, like it did other
times, the Range constructor would raise the expected exception.
But, this syntax appears as the condition of an if statement and the
special meaning of the … comes into play. Since 2 never “matches” (I
think it uses the Object#=~ method here?), the switch is never turned
on.

Whew!

Jacob F.