I ran across some code that was trying to validate that an integer
was in a given range, however the integer and the range were Strings.
The problem boils down to this:
...it seems like ('1'..'10').member?('2') should return true. The
problem lies in range.c, in the range_each_func() method. This method
starts with the first value, then calls succ() to get the next value,
breaking out of the loop when the value is no longer less than or equal
to the ending value (or strictly less than the ending value on an
exclusive range). Unfortunately, for the given string range this
happens immediately, since '2' > '10'.
I suppose that it could be argued that this is not a bug, but that
would be a difficult argument to win. Also, I need to make sure that
this is still a bug in the latest version of Ruby. Unfortunately, I'm
too sleepy to investigate further or create a patch for this tonight,
but I'll try to work on it some more tomorrow night (assuming nobody
else fixes it first).
I'd argue that it is not a bug, as there is no unique isomorphie from
strings to integers. Some well known functions would be hex, octal and
decimal encoding. I.e. '2' ... '10' could be understood as 2 ... 8, or
2 ... 16 or 2 ... 10 or error ... 2 depending on the base.
Only you can now what the string means, so convert it to an integer
and do the range test on integers.
So I think you should save your time on creating the patch and
preferably fix the application code.
Brian
···
On 23/11/05, Warren Brown <warrenbrown@aquire.com> wrote:
All,
I ran across some code that was trying to validate that an integer
was in a given range, however the integer and the range were Strings.
The problem boils down to this:
...it seems like ('1'..'10').member?('2') should return true. The
problem lies in range.c, in the range_each_func() method. This method
starts with the first value, then calls succ() to get the next value,
breaking out of the loop when the value is no longer less than or equal
to the ending value (or strictly less than the ending value on an
exclusive range). Unfortunately, for the given string range this
happens immediately, since '2' > '10'.
I suppose that it could be argued that this is not a bug, but that
would be a difficult argument to win. Also, I need to make sure that
this is still a bug in the latest version of Ruby. Unfortunately, I'm
too sleepy to investigate further or create a patch for this tonight,
but I'll try to work on it some more tomorrow night (assuming nobody
else fixes it first).
In message "Re: [BUG] string range membership" on Wed, 23 Nov 2005 15:41:32 +0900, "Warren Brown" <warrenbrown@aquire.com> writes:
I ran across some code that was trying to validate that an integer
was in a given range, however the integer and the range were Strings.
include? and member? compares with beg <= val <= end, which is
dictionary order for strings. Unfortunately strings generated from
using succ is not in dictionary order. I'm not sure how to solve
this.
I'd argue that it is not a bug, as there is no unique isomorphie from
strings to integers. Some well known functions would be hex, octal and
decimal encoding. I.e. '2' ... '10' could be understood as 2 ... 8, or
2 ... 16 or 2 ... 10 or error ... 2 depending on the base.
Only you can now what the string means, so convert it to an integer
and do the range test on integers.
I was going to make that argument, but I realized that #each (by way of #succ) *does* have some extra knowledge (or assumptions) about strings,
and it's pretty smart:
This was discussed sometime ago. The solution (mostly arrived at by
Peter Vanbroekhoven) is to use a different comparision method. In
Facets you'll find the #cmp method, which is part of the base methods,
and which is used by the Interval class --a true Interval as opposed to
what Range is.
def cmp(other)
return -1 if length < other.length
return 1 if length > other.length
self <=> other
end
Of course this won't be of use to tuple forms like "1.18.12", but in
such cases a Tuple object is in order anyway.