From: timr Date: 2010-08-24T10:55:09+09:00 Subject: Re: assert "foo"[3] != "foo"[3,1]...revisited Hi again, Thanks for responding to my question--it is something akin to getting a return letter from the President. And sorry for the previous reference to PoLS. Though I understand the current function of String#[] vs. String#[,] and can predict their output, I don't concede that anything gained by having a divergence in behavior at the end of a string. In fact, without the divergent behavior at the end of a string, the documentation could simply read: Element Reference—If passed a single Fixnum, returns the code of the character at that position. If passed two Fixnum objects, returns a substring starting at the offset given by the first, and a length given by the second. If given a range, a substring containing characters at offsets given by the range is returned. In all three cases, if an offset is negative, it is counted from the end of str. Returns nil if the initial offset falls outside the string, the length is negative, or the beginning of the range is greater than the end. (This is in fact how the documentation currently reads. If there were no edge cases to account for, one could leave it implied that the String#[] and String#[,] methods are predictably related with String#[] being equivalent to String#[,] with an implied second argument of 1.) However, as element referencing is currently implemented, the documentation may benefit from highlighting the edge-case at the end of strings. See below for an attempt... Please note edge-case when the index position is the same as the length of the string: "foo"[0] == "foo"[0,1] "foo"[1] == "foo"[1,1] "foo"[2] == "foo"[2,1] "foo"[3] != "foo"[3,1] #These are different (nil on the left and "" on the right). Just memorize this edge case. "foo"[3,1] = "d" #=> "food" "foo"[3] = "d" #=> IndexError. #And memorize also for good measure. And here is a proposal for the updated change to the documentation: Element Reference—If passed a single Fixnum, returns the code of the character at that position. At the end of the string, single parameter element referencing will return nil. If passed two Fixnum objects, returns a substring starting at the offset given by the first, and a length given by the second. At the end of the string, two-argument element referencing returns and empty string (""). If given a range, a substring containing characters at offsets given by the range is returned. In all three cases, if an offset is negative, it is counted from the end of str. Returns nil if the initial offset falls outside the string, the length is negative, or the beginning of the range is greater than the end. Of course, simplicity/elegance is in the mind of the beholder. But, I hope that you might consider the option of eliminating the divergent behavior of String#[] and String[,] when the index == str.length. Thanks, Tim On Aug 23, 5:40 am, Yukihiro Matsumoto wrote: > Hi, > > In message "Re: assert "foo"[3] != "foo"[3,1]...revisited" >     on Mon, 23 Aug 2010 20:10:23 +0900, Colin Bartlett writes: > > |I think it's worth adding something like Matz's > |wording to > |  http://www.ruby-doc.org/core/classes/String.html#M000771 > |  http://www.ruby-doc.org/core/classes/Array.html#M002160 > |because reasons for why things work a particular way do help people (well, > |at least me) remember behaviour. > > Yep, description proposal is welcome. > >                                                         matz.