Range#member? Oddity


#1

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 G. II


#2

James Edward G. II wrote:

=> false

James Edward G. II

I cannot duplicate this with 1.8.2 or 1.8.4.

  • Dan

#3

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

=> false
James Edward G. 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 G. II


#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


#5

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

=> false
James Edward G. II

I cannot duplicate this with 1.8.2 or 1.8.4.

I can.

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

~ ryan ~


#6

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 G. II removed_email_address@domain.invalid:


#7

Daniel B. wrote:

James Edward G. 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?

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]


#8

James Edward G. II wrote:

range.member?(“1”)

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

James Edward G. 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


#9

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 H. wrote:

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: removed_email_address@domain.invalid
800 Phillips Road TEL: 585.422.8078
Webster, NY 14580


#10

James Edward G. II wrote:

=> false

James Edward G. 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


#11

On Jan 13, 2006, at 3:16 PM, Matthew D. 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 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 G. II


#12

On Fri, 13 Jan 2006 22:16:14 +0100, Matthew D.
removed_email_address@domain.invalid
wrote:

range.member?(“2”)
you’re running into is that Range#member? is implemented as:
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

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


#13

The rdoc needs to be updated for Range#include? and Range#member? then.

~ ryan ~


#14

On Fri, 13 Jan 2006 23:00:37 +0100, James Edward G. II
removed_email_address@domain.invalid wrote:

James Edward G. II

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


#15

On Jan 13, 2006, at 3:58 PM, David V. 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 G. II


#16

No, those methods work perfectly. The behaviour of String is the problem
here.

On Fri, 13 Jan 2006 23:46:26 +0100, J. Ryan S. removed_email_address@domain.invalid


#17

On Sat, 14 Jan 2006 00:17:26 +0100, James Edward G. II
removed_email_address@domain.invalid wrote:

On Jan 13, 2006, at 5:04 PM, David V. wrote:

No, those methods work perfectly. The behaviour of String is the
problem here.

??? How exactly is it that you believe String should behave?

James Edward G. II

Well, to work well in Ranges, for any String s, s.succ > s must hold
true.

David V.


#18

On Jan 13, 2006, at 5:04 PM, David V. wrote:

No, those methods work perfectly. The behaviour of String is the
problem here.

??? How exactly is it that you believe String should behave?

James Edward G. II


#19

On Jan 13, 2006, at 6:54 PM, David V. wrote:

Well, to work well in Ranges, for any String s, s.succ > s must
hold true.

How about having Range use Object#strict_succ to generate
its sequence? Define String#strict_succ as needed to guarantee
s.succ > s and then alias strict_succ to succ for other classes
(such as Fixnum) so they don’t break when used in a Range.

Gary W.


#20

On Jan 13, 2006, at 5:54 PM, David V. wrote:

James Edward G. II

Well, to work well in Ranges, for any String s, s.succ > s must
hold true.

I’m pretty sure we don’t want to change the meaning of String
comparisons at this point. succ() just doesn’t happened to be
defined under those terms, because then it would be a lot less useful
to us. It’s hard for me to see any of that as “broken”.

James Edward G. II