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
<div id="eutpuhe">
UETHUEPUK
THEUTEUH
teuhepxn
thueonhoe
ononueuouh
</div>
</body>

and a three . range test give the same output.

ruby -e 'while gets; print if /<div id=.*$/ ... /<\/body>/; end' < fred
<div id="eutpuhe">
UETHUEPUK
THEUTEUH
teuhepxn
thueonhoe
ononueuouh
</div>
</body>

The original file 'fred' is

<html>
<title>hello</title>
<body>
<div id="eutpuhe">
UETHUEPUK
THEUTEUH
teuhepxn
thueonhoe
ononueuouh
</div>
</body>
</html>

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 Burrowes 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 http://www.cs.auckland.ac.nz/~rob
Private bag 92019 http://www.wikarekare.org
Auckland 1001 http://www.burrowes.org

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

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

I am also confused that

ruby -e 'while gets; print if /<div id=.*$/ .. /<\/body>/; end' < fred
<div id="eutpuhe">
UETHUEPUK
THEUTEUH
teuhepxn
thueonhoe
ononueuouh
</div>
</body>

and a three . range test give the same output.

ruby -e 'while gets; print if /<div id=.*$/ ... /<\/body>/; end' < fred
<div id="eutpuhe">
UETHUEPUK
THEUTEUH
teuhepxn
thueonhoe
ononueuouh
</div>
</body>

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 Fugal

···

On 5/3/06, Rob Burrowes <rob@cs.auckland.ac.nz> wrote:

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->

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

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

I am also confused that

ruby -e 'while gets; print if /<div id=.*$/ .. /<\/body>/; end' < fred
<div id="eutpuhe">
UETHUEPUK
THEUTEUH
teuhepxn
thueonhoe
ononueuouh
</div>
</body>

and a three . range test give the same output.

ruby -e 'while gets; print if /<div id=.*$/ ... /<\/body>/; end' < fred
<div id="eutpuhe">
UETHUEPUK
THEUTEUH
teuhepxn
thueonhoe
ononueuouh
</div>
</body>

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 Fugal

Rob

Rob Burrowes 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 http://www.cs.auckland.ac.nz/~rob
Private bag 92019 http://www.wikarekare.org
Auckland 1001 http://www.burrowes.org

···

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

On 5/3/06, Rob Burrowes <rob@cs.auckland.ac.nz> wrote:

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->

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->

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

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

I am also confused that

ruby -e 'while gets; print if /<div id=.*$/ .. /<\/body>/; end' < fred
<div id="eutpuhe">
UETHUEPUK
THEUTEUH
teuhepxn
thueonhoe
ononueuouh
</div>
</body>

and a three . range test give the same output.

ruby -e 'while gets; print if /<div id=.*$/ ... /<\/body>/; end' < fred
<div id="eutpuhe">
UETHUEPUK
THEUTEUH
teuhepxn
thueonhoe
ononueuouh
</div>
</body>

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 Fugal

Rob

Rob Burrowes 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 http://www.cs.auckland.ac.nz/~rob
Private bag 92019 http://www.wikarekare.org
Auckland 1001 http://www.burrowes.org

Rob

Rob Burrowes 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 http://www.cs.auckland.ac.nz/~rob
Private bag 92019 http://www.wikarekare.org
Auckland 1001 http://www.burrowes.org

···

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

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

On 5/3/06, Rob Burrowes <rob@cs.auckland.ac.nz> wrote:

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->

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->

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->

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

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

I am also confused that

ruby -e 'while gets; print if /<div id=.*$/ .. /<\/body>/; end' < fred
<div id="eutpuhe">
UETHUEPUK
THEUTEUH
teuhepxn
thueonhoe
ononueuouh
</div>
</body>

and a three . range test give the same output.

ruby -e 'while gets; print if /<div id=.*$/ ... /<\/body>/; end' < fred
<div id="eutpuhe">
UETHUEPUK
THEUTEUH
teuhepxn
thueonhoe
ononueuouh
</div>
</body>

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 Fugal

Rob

Rob Burrowes 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

Rob

Rob Burrowes 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

Rob

Rob Burrowes 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 4/05/2006, at 1:00 PM, Rob Burrowes wrote:

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

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

On 5/3/06, Rob Burrowes <rob@cs.auckland.ac.nz> wrote:

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

the === seems to bind before the ...

;D

···

On 5/4/06, Rob Burrowes <rob@cs.auckland.ac.nz> wrote:

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 Burrowes wrote:

> 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 Fugal wrote:
>
>> On 5/3/06, Rob Burrowes <rob@cs.auckland.ac.nz> wrote:
>>> 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
>>
>> 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
>>
>>> I am also confused that
>>>
>>> ruby -e 'while gets; print if /<div id=.*$/ .. /<\/body>/; end'
>>> < fred
>>> <div id="eutpuhe">
>>> UETHUEPUK
>>> THEUTEUH
>>> teuhepxn
>>> thueonhoe
>>> ononueuouh
>>> </div>
>>> </body>
>>>
>>> and a three . range test give the same output.
>>>
>>> ruby -e 'while gets; print if /<div id=.*$/ ... /<\/body>/; end'
>>> < fred
>>> <div id="eutpuhe">
>>> UETHUEPUK
>>> THEUTEUH
>>> teuhepxn
>>> thueonhoe
>>> ononueuouh
>>> </div>
>>> </body>
>>
>> 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 Fugal
>>
>
> Rob
>
> Rob Burrowes 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 http://www.cs.auckland.ac.nz/~rob
> Private bag 92019 http://www.wikarekare.org
> Auckland 1001 http://www.burrowes.org
>

Rob

Rob Burrowes 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 http://www.cs.auckland.ac.nz/~rob
Private bag 92019 http://www.wikarekare.org
Auckland 1001 http://www.burrowes.org

--
Daniel Baird
http://danielbaird.com (TiddlyW;nks! :: Whiteboard Koala :: Blog :: Things
That Suck)

=== has higher precendence than the ... operator

2...5 === x is

2...(5 === x)

without parens

···

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

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

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 Fugal

···

On 5/3/06, Rob Burrowes <rob@cs.auckland.ac.nz> wrote: