On Thu, 22 Jul 2004, Mark Hubbart wrote:

> This seems right to me... aren't these two expressions equivalent?
>
>   'foobar'[-1..-2]
>     ==>""
>   'foobar'[5..4]
>     ==>""

yes - both are broken by exactly the same bug!  ;-)

> I admit that the beginning being lower than the end is a little strange
> at first,

??

-1 > -2 and 5 > 4 so i assume you mean 'beginning being __higher__ than the end'

??


> but I understood it to be an artifact of the range type.  Since 1..2
> includes the end number,

i assume you mean -1..-2 here, and it (the range) does not seem to think it
includes the end number:

   ~ > irb
   irb(main):001:0> (-1..-2).include? -2
   => false

nor the starting point for that matter!

   irb(main):002:0> (-1..-2).include? -1
   => false

how can a range not include it's starting point - even if it's going backwards?

> it makes sense that the only way to get an empty string would be to go
> backwards...

nothing else about ranges can go backwards though:

   irb(main):001:0> (0..-42).to_a
   => []

and everything about backward ranges is broken and/or inconsistent (see
above).  if you read the source for rb_range_beg_len you'll see that backward
ranges are actively serached for (len < 0) and an exception thrown (or Qnil
retruned if err == 0) if one is found.  that's why

   irb(main):001:0> 'foobar'[-1..-3]
   => nil

also, the docs claim otherwise with no mention of this special range feature:

   /*
    *     a = "hello there"
    *     a[1]                   #=> 101
    *     a[1,3]                 #=> "ell"
    *     a[1..3]                #=> "ell"
    *     a[-3,2]                #=> "er"
    *     a[-4..-2]              #=> "her"
    *     a[-2..-4]              #=> nil
    *     a[/[aeiou](.)\1/]      #=> "ell"
    *     a[/[aeiou](.)\1/, 0]   #=> "ell"
    *     a[/[aeiou](.)\1/, 1]   #=> "l"
    *     a[/[aeiou](.)\1/, 2]   #=> nil
    *     a["lo"]                #=> "lo"
    *     a["bye"]               #=> nil
    */

so there's nothing in the code that suggests 'backward' ranges where end =
start -1 (-1..-2) should be handled any differently.  the reason they are
handled differently appears to be an off by one error cause by mapping negative
indexes to positive ones and then handling them the exactly same - remember the
absolute value of the range of negative indexes is off by one from the absolute
value of the range of positive indexes...

> Correct me if I'm wrong, but doesn't that make it impossible to reference an
> empty string between characters?

yes.  and it i think it should.  you cannot reference this empty string using
positive indexes at all, nor negative ones EXCEPT for the special case of end =
beg -1 (-1..-2).

you can always reference the empty string using offset plus len == 0

   ~ > irb
   irb(main):001:0> s='foobar'
   => "foobar"

   irb(main):002:0> s[4,0]
   => ""

   irb(main):003:0> s[4,0] = '<emtpy>'
   => "<emtpy>"

   irb(main):004:0> s
   => "foob<emtpy>ar"

cheers.


-a
--
===============================================================================
| EMAIL   :: Ara [dot] T [dot] Howard [at] noaa [dot] gov
| PHONE   :: 303.497.6469
| A flower falls, even though we love it;
| and a weed grows, even though we do not love it. 
|   --Dogen
===============================================================================