Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

In many languages, the substring function works like this:

substring(startIndex, endIndex)

returns the substring from startIndex until endIndex-1 (if you view startIndex and endIndex as 0-based) / from startIndex+1 to endIndex (1-based)

This is confusing. I understand that the two parameters can be interpreted as "startIndex" and "length of the substring", but in my opinion that is still confusing and even in this case, startIndex is 0-based while length is 1-based.

Why not stick to one convention for both the function arguments? and why do newer languages like ruby and python continue to stick to this standard?

share|improve this question
3  
length = endIndex - startIndex –  Giorgio Jul 19 '12 at 6:05
1  
Also, to get the tail end of a string: tail = str.substring(startIndex, str.length) –  Baqueta Jul 19 '12 at 9:09
2  
This isn't really language agnostic. In many languages the second parameter is length and not endIndex. –  CodesInChaos Jul 19 '12 at 10:23
add comment

3 Answers

up vote 8 down vote accepted

The second argument is not the "length of the substring", that only works if you start at the very beginning of the string. The point is that specifying "from".."to" is linguistically ambiguous: you name two limit values, but do you want those two values themselves included in the extracted range or not? In normal parlance, there isn't a strong conventional preference: "I knew her from first to fourth grade" means "for four years", but "training is from one to three" means "two hours", not three.

Therefore, it would be a major source of confusion if the indices referred to characters in a string. What they really refer to is the positions between the characters: 0 means "before the string", 1 means "after the first character", 2 means "after the second character" etc. Therefore, s.substring(0,2) means "The first two characters of s", unambiguously. (The fact that endIndex - startIndex == length(extract) is admittedly a nice bonus.)

share|improve this answer
1  
"Therefore, it would be a major source of confusion if the indices referred to characters in a string." Would it? I don't see why it would be any more ambiguous than referring to the "positions between the characters". –  Baqueta Jul 19 '12 at 8:57
3  
Ranges are indeed ambiguous in general. But that's what conventions and documentation are for. For instance, ranges in Python are always half-open. –  delnan Jul 20 '12 at 16:01
add comment

There are reasons why Python and Ruby use the convention you describe. These reasons may not be immediately evident -- but experience, and reasoned explanations (transcribed) by well-respected language designers, give good reason to think that zero-based, half-open array ranges are the least error-prone of many possible options.

@KilianFoth's answer gives a common and useful mnemonic for visualizing and using this convention. But the reason newer languages use the convention is because it works.

share|improve this answer
add comment

For situations where [3,6] would mean the third, fourth, and fifth characters, but not the sixth, I would suggest that it may be helpful to imagine the characters as occupying space on a number line, with indices representing points between the characters. The first character would sit in the space between 0 and 1, the next between 1 and 2, then 2..3, etc. The range [3,6] would include the spaces from 3..4, 4..5, and 5..6. By convention, using just a single subscript n will refer to the range (n)..(n+1).

Viewed in this fashion, it becomes clear that [3,6] and [6,8] refer to two touching but not overlapping ranges of characters, since they occupy touching but non-overlapping space on the number line.

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.