Я знайшов пояснення Гарі Райт також дуже корисним.
http://www.ruby-forum.com/topic/1393096#990065
Відповідь Гарі Райт -
http://www.ruby-doc.org/core/classes/Array.html
Документи, безумовно, можуть бути більш зрозумілими, але фактична поведінка є послідовною та корисною. Примітка. Я припускаю версію String 1.9.X.
Це допомагає розглянути нумерацію наступним чином:
-4 -3 -2 -1 <-- numbering for single argument indexing
0 1 2 3
+---+---+---+---+
| a | b | c | d |
+---+---+---+---+
0 1 2 3 4 <-- numbering for two argument indexing or start of range
-4 -3 -2 -1
Поширеною (і зрозумілою) помилкою є занадто припущення, що семантика єдиного індексу аргументу є такою ж, як семантика
першого аргументу у двох сценаріях (або діапазоні) аргументів. На практиці це не одне і те ж, і документація цього не відображає. Однак помилка, безумовно, є в документації, а не в реалізації:
один аргумент: індекс представляє позицію одного символу в рядку. Результатом є або рядок одного символу, знайдений в індексі, або нуль, оскільки в даному індексі немає символу.
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
два цілі аргументи: аргументи ідентифікують частину рядка для вилучення або заміни. Зокрема, рядки нульової ширини рядка також можуть бути ідентифіковані, щоб текст можна було вставити до або після існуючих символів, у тому числі на передній або кінці рядка. У цьому випадку перший аргумент не визначає позицію символу, а натомість ідентифікує пробіл між символами, як показано на схемі вище. Другий аргумент - довжина, яка може бути 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"
Поведінка діапазону досить цікава. Вихідною точкою є те саме, що і перший аргумент, коли подано два аргументи (як описано вище), але кінцевою точкою діапазону може бути "позиція символів", як при одному індексуванні, або "крайова позиція", як при двох цілих аргументах. Різниця визначається тим, чи використовується діапазон з двома точками або діапазон з трьома точками:
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.
Якщо ви повернетесь до цих прикладів і наполягаєте на використанні єдиної семантики індексу для прикладів подвійного або діапазонного індексування, ви просто заплутаєтесь. Ви повинні використовувати альтернативну нумерацію, яку я показую на діаграмі ascii, для моделювання фактичної поведінки.