···
On Fri, May 14, 2010 at 4:40 AM, Vikrant Chaudhary <nasa42@gmail.com> wrote:
Hi,
If I do -
('A'..'Z').include?('AA')
It returns "true", while
('A'..'Z').to_a.include?('AA')
(of course) returns "false". Is it intentional or possibly a bug?
I'm using ruby 1.8.7 (2010-01-10 patchlevel 249) [x86_64-linux] on
Ubuntu 10.04 x64
*
* Returns <code>true</code> if <i>obj</i> is an element of
* <i>rng</i>, <code>false</code> otherwise. Conveniently,
* <code>===</code> is the comparison operator used by
* <code>case</code> statements.
*
* case 79
* when 1..50 then print "low\n"
* when 51..75 then print "medium\n"
* when 76..100 then print "high\n"
* end
*
* <em>produces:</em>
*
* high
*/
static VALUE
range_include(range, val)
VALUE range, val;
{
VALUE beg, end;
beg = rb_ivar_get(range, id_beg);
end = rb_ivar_get(range, id_end);
if (r_le(beg, val)) {
if (EXCL(range)) {
if (r_lt(val, end)) return Qtrue;
}
else {
if (r_le(val, end)) return Qtrue;
}
}
return Qfalse;
}
However, when it converts to an array, that is a method from Enumerable. I'm
not initiated enough to figure out how it's C code works, but my
understanding is that it uses #succ (I got that from this thread
Bizarre Range behavior - Ruby - Ruby-Forum, but please correct me if I
misunderstood) to iterate from the beginning element to the end element, to
create the array. Here is it's code, if you understand it, feel free to
explain.
(http://svn.ruby-lang.org/repos/ruby/branches/ruby_1_8/enum.c\)
/*
* call-seq:
* enum.to_a => array
* enum.entries => array
*
* Returns an array containing the items in <i>enum</i>.
*
* (1..7).to_a #=> [1, 2, 3, 4, 5, 6, 7]
* { 'a'=>1, 'b'=>2, 'c'=>3 }.to_a #=> [["a", 1], ["b", 2], ["c", 3]]
*/
static VALUE
enum_to_a(argc, argv, obj)
int argc;
VALUE *argv;
VALUE obj;
{
VALUE ary = rb_ary_new();
rb_block_call(obj, id_each, argc, argv, collect_all, ary);
return ary;
}
Then Array#include iterates through each of it's elements to check if it
contains the desired element
(http://svn.ruby-lang.org/repos/ruby/branches/ruby_1_8/array.c\)
/*
* call-seq:
* array.include?(obj) -> true or false
*
* Returns <code>true</code> if the given object is present in
* <i>self</i> (that is, if any object <code>==</code> <i>anObject</i>),
* <code>false</code> otherwise.
*
* a = [ "a", "b", "c" ]
* a.include?("b") #=> true
* a.include?("z") #=> false
*/
VALUE
rb_ary_includes(ary, item)
VALUE ary;
VALUE item;
{
long i;
for (i=0; i<RARRAY(ary)->len; i++) {
if (rb_equal(RARRAY(ary)->ptr[i], item)) {
return Qtrue;
}
}
return Qfalse;
}
The elements the array contains are
$ ruby -e "p ('A'..'Z').to_a"
["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O",
"P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"]
So "AA" is not found, and thus it returns false.
I honestly don't know about 1.9, I tried looking at it's code, but I don't
understand it.
(http://svn.ruby-lang.org/repos/ruby/branches/ruby_1_9_1/range.c\)