Forum: Ruby Newbee Question on what if x === 2..5 does

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
Rob B. (Guest)
on 2006-05-04 02:51
(Received via mailing list)
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 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                http://www.cs.auckland.ac.nz/~rob
Private bag 92019                http://www.wikarekare.org
Auckland 1001                    http://www.burrowes.org
Jacob F. (Guest)
on 2006-05-04 03:09
(Received via mailing list)
On 5/3/06, Rob B. <removed_email_address@domain.invalid> 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

> </body>
> </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 F.
Rob B. (Guest)
on 2006-05-04 04:43
(Received via mailing list)
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.
>> </body>
>    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                http://www.cs.auckland.ac.nz/~rob
Private bag 92019                http://www.wikarekare.org
Auckland 1001                    http://www.burrowes.org
Rob B. (Guest)
on 2006-05-04 05:01
(Received via mailing list)
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
>>
>>> <div id="eutpuhe">
>>> ruby -e 'while gets; print  if /<div id=.*$/ ... /<\/body>/; end'
>> Sorry, can't help you there. I always have a hard time remembering
>>
> 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 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                http://www.cs.auckland.ac.nz/~rob
Private bag 92019                http://www.wikarekare.org
Auckland 1001                    http://www.burrowes.org
Rob B. (Guest)
on 2006-05-04 05:13
(Received via mailing list)
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                http://www.cs.auckland.ac.nz/~rob
Private bag 92019                http://www.wikarekare.org
Auckland 1001                    http://www.burrowes.org
Daniel B. (Guest)
on 2006-05-04 05:20
(Received via mailing list)
Try using:
  if (2...5) === x

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

;D
Logan C. (Guest)
on 2006-05-04 05:20
(Received via mailing list)
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
Jacob F. (Guest)
on 2006-05-04 19:49
(Received via mailing list)
On 5/3/06, Rob B. <removed_email_address@domain.invalid> 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.
This topic is locked and can not be replied to.