Мне также очень помогло объяснение Гари Райта.
http://www.ruby-forum.com/topic/1393096#990065
Ответ Гари Райта -
http://www.ruby-doc.org/core/classes/Array.html
Документы, конечно, могут быть более понятными, но фактическое поведение является последовательным и полезным. Примечание: я предполагаю, что 1.9.X версия String.
Это помогает рассмотреть нумерацию следующим образом:
-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, чтобы смоделировать реальное поведение.