Range#member? Oddity

I'm not understanding what I am seeing here. Can anyone please explain why the last line of this session gives *false* as an answer?

>> range = ("1".."10")
=> "1".."10"
>> range.to_a
=> ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"]
>> range.member?("1")
=> true
>> range.member?("2")
=> false

James Edward Gray II

James Edward Gray II wrote:

I'm not understanding what I am seeing here. Can anyone please explain why the last line of this session gives *false* as an answer?

>> range = ("1".."10")
=> "1".."10"
>> range.to_a
=> ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"]
>> range.member?("1")
=> true
>> range.member?("2")
=> false

James Edward Gray II

I cannot duplicate this with 1.8.2 or 1.8.4.

- Dan

it gets odder:

irb(main):001:0> range = ("1".."10")
=> "1".."10"
irb(main):002:0> range.to_a
=> ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"]
irb(main):003:0> range.member?("1")
=> true
irb(main):004:0> range.member?("2")
=> false
irb(main):005:0> range.member?("4")
=> false
irb(main):006:0> range.member?("9")
=> false
irb(main):007:0> range.member?("10")
=> true
irb(main):008:0> range.include?("2")
=> false
irb(main):009:0> range.include?("1")
=> true
irb(main):010:0> range === "1"
=> true
irb(main):011:0> range === "2"
=> false
irb(main):012:0> RUBY_VERSION
=> "1.8.2"

···

2006/1/13, James Edward Gray II <james@grayproductions.net>:

I'm not understanding what I am seeing here. Can anyone please
explain why the last line of this session gives *false* as an answer?

>> range = ("1".."10")
=> "1".."10"
>> range.to_a
=> ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"]
>> range.member?("1")
=> true
>> range.member?("2")
=> false

James Edward Gray II

James Edward Gray II wrote:

I'm not understanding what I am seeing here. Can anyone please explain why the last line of this session gives *false* as an answer?

>> range = ("1".."10")
=> "1".."10"
>> range.to_a
=> ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"]
>> range.member?("1")
=> true
>> range.member?("2")
=> false

James Edward Gray II

Hi,

There was some discussion about this in the recent past. If my memory serves me right (certainly an infrequent happening), the issue that you're running into is that Range#member? is implemented as:
class Range
    def member?(val)
       if self.exclude_end?
           (self.first <= val) and (val < self.last)
       else
          (self.first <= val) and (val <= self.last)
       end
    end
end

You should find this in both 1.8.2 and 1.8.4 I think.

There's a previous thread on ruby-talk about it, here's a link to somewhere near the conclusion of the discussion:
http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/167194

Matthew

Hi,

···

Am Samstag, 14. Jan 2006, 05:49:56 +0900 schrieb James Edward Gray II:

I'm not understanding what I am seeing here. Can anyone please
explain why the last line of this session gives *false* as an answer?

>> range = ("1".."10")
=> "1".."10"
>> range.to_a
=> ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"]
>> range.member?("1")
=> true
>> range.member?("2")
=> false

irb(main):006:0> 2 < 10
=> true
irb(main):007:0> "2" < "10"
=> false

Bertram

--
Bertram Scharpf
Stuttgart, Deutschland/Germany
http://www.bertram-scharpf.de

James Edward Gray II wrote:

I'm not understanding what I am seeing here. Can anyone please explain why the last line of this session gives *false* as an answer?

>> range = ("1".."10")
=> "1".."10"
>> range.to_a
=> ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"]
>> range.member?("1")
=> true
>> range.member?("2")
=> false

In short: Don't do this.

String ranges are very weird. They don't obey the rule that
x.succ > x.

Since "2" > "10", "2" is considered outside the range entirely.

If you really want to do this kind of thing, say
("1".."10").to_a.member?("2")

Hal

James Edward Gray II schrieb:

I'm not understanding what I am seeing here. Can anyone please explain why the last line of this session gives *false* as an answer?

>> range = ("1".."10")
=> "1".."10"
>> range.to_a
=> ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"]
>> range.member?("1")
=> true
>> range.member?("2")
=> false

James Edward Gray II

I don't know why to_a is working here.
I know that a range from '1' to '10' could be like you described, but it doesn't make a logical sense I think.
like ('a'..'ah') what should that be?
[a-255.chr] and all a[0.chr-255.chr]?

This is what I think, of course.
Dunno if it makes sense :>

MfG
Retze

Odd. I'm using 1.8.4:

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

James Edward Gray II

···

On Jan 13, 2006, at 2:54 PM, Daniel Berger wrote:

James Edward Gray II wrote:

I'm not understanding what I am seeing here. Can anyone please explain why the last line of this session gives *false* as an answer?
>> range = ("1".."10")
=> "1".."10"
>> range.to_a
=> ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"]
>> range.member?("1")
=> true
>> range.member?("2")
=> false
James Edward Gray II

I cannot duplicate this with 1.8.2 or 1.8.4.

It happens in 1.8.2 for me. It shows "1" and "10" as being in the range, but nothing else.

[justinc@justinc-dsktp ~]$ ruby -v
ruby 1.8.2 (2004-12-25) [i586-linux-gnu]
[justinc@justinc-dsktp ~]$ irb
irb(main):001:0> range = ("1".."10")
=> "1".."10"
irb(main):002:0> range.to_a
=> ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"]
irb(main):003:0> range.member?("1")
=> true
irb(main):004:0> range.member?("2")
=> false
irb(main):005:0> range.member?("10")
=> true
irb(main):006:0>

Note that range _isn't_ getting converted into an array.

-Justin

Daniel Berger wrote:

···

James Edward Gray II wrote:

I'm not understanding what I am seeing here. Can anyone please explain why the last line of this session gives *false* as an answer?

>> range = ("1".."10")
=> "1".."10"
>> range.to_a
=> ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"]
>> range.member?("1")
=> true
>> range.member?("2")
=> false

James Edward Gray II

I cannot duplicate this with 1.8.2 or 1.8.4.

- Dan

Daniel Berger wrote:

James Edward Gray II wrote:

I'm not understanding what I am seeing here. Can anyone please explain why the last line of this session gives *false* as an answer?
<snip>

I cannot duplicate this with 1.8.2 or 1.8.4.

- Dan

I'm getting this too. 1 and 10 both return true, everything else returns false.

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

I can.

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

~ ryan ~

···

On Jan 13, 2006, at 3:54 PM, Daniel Berger wrote:

James Edward Gray II wrote:

I'm not understanding what I am seeing here. Can anyone please explain why the last line of this session gives *false* as an answer?
>> range = ("1".."10")
=> "1".."10"
>> range.to_a
=> ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"]
>> range.member?("1")
=> true
>> range.member?("2")
=> false
James Edward Gray II

I cannot duplicate this with 1.8.2 or 1.8.4.

This cleared it up for me. Thank you.

I was aware of the old system, where member?() and include?() had separate meanings and just didn't know it had been abandoned.

James Edward Gray II

···

On Jan 13, 2006, at 3:16 PM, Matthew Desmarais wrote:

There's a previous thread on ruby-talk about it, here's a link to somewhere near the conclusion of the discussion:
http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/167194

This would seem to make it an oddity of String#succ, that behaving automagically, not generating successors with respect to String comparison.

E.g. for any Integers i, i.succ > i. For some strings, that does't hold true.

Bottom line: Don't use strings when you're really using numbers. Like in mathemathical contexts. D'oh. You could possibly hack around that in Range code to provide for data types where generating successors is inconsistent with comparison, but I wouldn't like to see that.

David Vallner

···

On Fri, 13 Jan 2006 22:16:14 +0100, Matthew Desmarais <desmarm@gmail.com> wrote:

James Edward Gray II wrote:

I'm not understanding what I am seeing here. Can anyone please explain why the last line of this session gives *false* as an answer?

>> range = ("1".."10")
=> "1".."10"
>> range.to_a
=> ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"]
>> range.member?("1")
=> true
>> range.member?("2")
=> false

James Edward Gray II

Hi,

There was some discussion about this in the recent past. If my memory serves me right (certainly an infrequent happening), the issue that you're running into is that Range#member? is implemented as:
class Range
    def member?(val)
       if self.exclude_end?
           (self.first <= val) and (val < self.last)
       else
          (self.first <= val) and (val <= self.last)
       end
    end
end

You should find this in both 1.8.2 and 1.8.4 I think.

There's a previous thread on ruby-talk about it, here's a link to somewhere near the conclusion of the discussion:
http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/167194

Matthew

Hal Fulton wrote:

James Edward Gray II wrote:

=> false

In short: Don't do this.

String ranges are very weird. They don't obey the rule that
x.succ > x.

Since "2" > "10", "2" is considered outside the range entirely.

If you really want to do this kind of thing, say
("1".."10").to_a.member?("2")

Hal

If the two strings have the same length, the weirdness disappears.

Christer

···

--
Posted via http://www.ruby-forum.com/\.

James Edward Gray II wrote:

···

On Jan 13, 2006, at 2:54 PM, Daniel Berger wrote:

James Edward Gray II wrote:

I'm not understanding what I am seeing here. Can anyone please explain why the last line of this session gives *false* as an answer?
>> range = ("1".."10")
=> "1".."10"
>> range.to_a
=> ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"]
>> range.member?("1")
=> true
>> range.member?("2")
=> false
James Edward Gray II

I cannot duplicate this with 1.8.2 or 1.8.4.

Odd. I'm using 1.8.4:

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

James Edward Gray II

Whoops, I misspoke. I was using numbers, not strings. I do, in fact, get the same behavior in 1.8.4 (and 1.8.2).

/me guesses randomly that it has something to do with stringified numbers in particular.

Regards,

Dan

I don't know for sure but my guess has something to do with numbers vs
characters and whether "1".."10" expands to the same thing that 1..10
does.

range=(1..10)

1..10

range.member?(1)

true

range.member?(2)

true

range.member?(3)

true

puts range

1..10

   Huh???

-dwh-

···

On Fri, 2006-01-13 at 16:01, Daniel Harple wrote:

Daniel Berger wrote:
> James Edward Gray II wrote:
>> I'm not understanding what I am seeing here. Can anyone please
>> explain why the last line of this session gives *false* as an answer?
>> <snip>
>
> I cannot duplicate this with 1.8.2 or 1.8.4.
>
> - Dan

I'm getting this too. 1 and 10 both return true, everything else
returns false.

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

--
I not only live each endless day in grief, but live each day
thinking about living each day in grief.
                                              -- C.S. Lewis

Daniel W. Hinz Xerox Corp: XOG/SEBU/MCD/EIDC/ISM&D
MS: 111-03J e-mail: dhinz@eng.mc.xerox.com
800 Phillips Road TEL: 585.422.8078
Webster, NY 14580

You could possibly hack around that in Range code to provide for data types where generating successors is inconsistent with comparison, but I wouldn't like to see that.

It's not too tough in this case:

>> ("1".."10").to_a.include?("2")
=> true

James Edward Gray II

···

On Jan 13, 2006, at 3:58 PM, David Vallner wrote:

Christer Nilsson schrieb:

Hal Fulton wrote:

String ranges are very weird. They don't obey the rule that
x.succ > x.

Since "2" > "10", "2" is considered outside the range entirely.

If you really want to do this kind of thing, say
("1".."10").to_a.member?("2")

If the two strings have the same length, the weirdness disappears.

Very good point!

Regards,
Pit

Hi --

···

On Sat, 14 Jan 2006, Christer Nilsson wrote:

Hal Fulton wrote:

James Edward Gray II wrote:

=> false

In short: Don't do this.

String ranges are very weird. They don't obey the rule that
x.succ > x.

Since "2" > "10", "2" is considered outside the range entirely.

If you really want to do this kind of thing, say
("1".."10").to_a.member?("2")

Hal

If the two strings have the same length, the weirdness disappears.

But other weirdnesses arise :slight_smile:

irb(main):019:0> ("A".."z").member?("g")
=> true
irb(main):020:0> ("A".."z").to_a.include?("g")
=> false

David

--
David A. Black
dblack@wobblini.net

"Ruby for Rails", from Manning Publications, coming April 2006!

Yes, that always works, but it beats the point of having first class ranges as opposed to just having a pythonesque range function in the first place. I'd personally rather coerce the strings to numbers if I know they represent such to get more type safety and possibly some execution speed too.

David Vallner

···

On Fri, 13 Jan 2006 23:00:37 +0100, James Edward Gray II <james@grayproductions.net> wrote:

On Jan 13, 2006, at 3:58 PM, David Vallner wrote:

You could possibly hack around that in Range code to provide for data types where generating successors is inconsistent with comparison, but I wouldn't like to see that.

It's not too tough in this case:

>> ("1".."10").to_a.include?("2")
=> true

James Edward Gray II