Forum: Ruby Array#slice's boundary special case.why?

12a71a456ac3d464914a8267f11d43b3?d=identicon&s=25 Shane Emmons (Guest)
on 2011-04-14 17:25
(Received via mailing list)
Can anyone give me the background on why given the following:
  arr = %w(0 1 2 3 4)

Then arr[5,1] returns [] and arr[6,1] returns nil? I understand that the
last element +1 is labeled a special case, but why?
54404bcac0f45bf1c8e8b827cd9bb709?d=identicon&s=25 7stud -- (7stud)
on 2011-04-14 18:22
You're in luck.  Gary Wright recently posted the definitive word on that
phenomenon:

Gary Wright wrote in post #990065:
> On Mar 30, 2011, at 2:08 PM, 7stud -- wrote:
>>>
>>> s[3,0] is "", instead of nil.
>>
>> That behaviour is contrary to the description in the 1.9.2 docs here:
>>
>>    http://www.ruby-doc.org/core/classes/Array.html
>
> The docs certainly could be more clear but the actual behavior is
> self-consistent and useful.
> Note: I'm assuming 1.9.X version of String.
>
>  It helps to consider the numbering in the following way:
>
>   -4  -3  -2  -1    <-- numbering for single argument indexing
>    0   1   2   3
>  +---+---+---+---+
>  | a | b | c | d |
>  +---+---+---+---+
>  0   1   2   3   4  <-- numbering for 2 argument indexing/start of range
> -4  -3  -2  -1
>
> The common (and understandable) mistake is too assume that the semantics
> of the single argument index are the same as the semantics of the
> *first* argument in the two argument scenario (or range).  They are not
> the same thing in practice and the documentation doesn't reflect this.
> The error though is definitely in the documentation and not in the
> implementation:
>
> single argument:  the index represents a single character position
> within the string.  The result is either the single character string
> found at the index or nil because there is no character at the given
> index.
>
>   s = ""
>   s[0]    # nil because no character at that position
>
>   s = "abcd"
>   s[0]    # "a"
>   s[-4]   # "a"
>   s[-5]   # nil, no characters before the first one
>
> two integer arguments: the arguments identify a portion of the string to
> extract or to replace.  In particular, zero-width portions of the string
> can also be identified so that text can be inserted before or after
> existing characters including at the front or end of the string. In this
> case, the first argument does *not* identify a character position but
> instead identifies the space between characters as shown in the diagram
> above.  The second argument is the length, which can be 0.
>
> s = "abcd"   # each example below assumes s is reset to "abcd"
>
> To insert text before 'a':   s[0,0] = "X"           #  "Xabcd"
> To insert text after 'd':    s[4,0] = "Z"           #  "abcdZ"
> To replace first two characters: s[0,2] = "AB"      #  "ABcd"
> To replace last two characters:  s[-2,2] = "CD"     #  "abCD"
> To replace middle two characters: s[1..3] = "XX"    #  "aXXd"
>
> The behavior of a range is pretty interesting. The starting point is the
> same as the first argument when two arguments are provided (as described
> above) but the end point of the range can be the 'character position' as
> with single indexing or the "edge position" as with two integer
> arguments.  The difference is determined by whether the double-dot range
> or triple-dot range is used:
>
> s = "abcd"
> s[1..1]           # "b"
> s[1..1] = "X"     # "aXcd"
>
> s[1...1]          # ""
> s[1...1] = "X"    # "aXbcd", the range specifies a zero-width portion of
> the string
>
> s[1..3]           # "bcd"
> s[1..3] = "X"     # "aX",  positions 1, 2, and 3 are replaced.
>
> s[1...3]          # "bc"
> s[1...3] = "X"    # "aXd", positions 1, 2, but not quite 3 are replaced.
>
>
> If you go back through these examples and insist and using the single
> index semantics for the double or range indexing examples you'll just
> get confused.  You've got to use the alternate numbering I show in the
> ascii diagram to model the actual behavior.
>
>
> Gary Wright

a
a
a
a
a
a
aa
a
a
a
a
a
a
a
a
a

aa

a
a


a
a
a
a

a
a
a
a

a
a
99804651e19d8b0dffbc0da53e39114e?d=identicon&s=25 Adam Prescott (Guest)
on 2011-04-14 18:37
(Received via mailing list)
This comes up periodically.

You can see http://www.ruby-forum.com/topic/1393096 which has quite a
good
explanation (one which I'd like to see in the documentation).

There is also http://redmine.ruby-lang.org/issues/4541
Please log in before posting. Registration is free and takes only a minute.
Existing account

NEW: Do you have a Google/GoogleMail, Yahoo or Facebook account? No registration required!
Log in with Google account | Log in with Yahoo account | Log in with Facebook account
No account? Register here.