Hi
I'm an Art and CG student learning Python and today's exercise was about positions in a tiled room. The fact that I had to check if a position was inside the room and given that in a 1x1 room, 0.0 was considered in and 1.0 was considered out, it kept me thinking about 0-base indexing iterables and slicing.
Read some articles and discussions, some pros and cons to each 0-base and 1-base, concerns about slicing, etc. But ultimately the question that got stuck in me and didn't found an answer was: Why can't both 0-base and 1-base indexing exist in the same language, and why can't slicing be customized?
If I'm indexing the ruler marks, intervals, boundaries, dots, makes sense to start of at 0; rul=[0,1,2,3,4,5,6] would index every mark on my ruler so that accordingly rul[0]=0, rul[5]=5. If I'm indexing the blue circles, natural number quantities, objects, spans, makes sense to start at 1; cir= [1,2,3,4,5] so that cir[1]=1 and cir[5]=5.
Now, a lot of the discussion was to do with slicing coupled with the indexing and I don't totally understand why.
a ≤ x < b is not so intuitive when dealing with objects ("I want balls 1 up to the the one before 3"), so on one side, you put the finger on what you want and on the other, on what you don't want. But this method does have the neat property of producing neighbor selections that border perfectly, as in [:a][a:b][b:c]. Although in inverse order(-1), the results can be unexpected as it returns values off-by-one from its counterpart like; L=[0,1,2,3,4,5] so that L[1:3]=[1,2] and L[3:1:-1]=[3:2]. So it's consistent with the rule a ≤ x < b, grabbing the lower limit item, but it can feel strange by not producing the same selection with inverse order.
a ≤ x ≤ b is a natural way to select objets ("I want the balls 1 up to 3"), so you're putting the finger on the things you want. If you inverse the order(-1) it's still very easy to grasp what are you picking because whatever you select it's included like: L=[0,1,2,3,4,5] so that L[1:3]=[1,2,3] and L[3:1:-1]=[3,2,1]. Problems seem to arrive though, when trying to do neighbor selections, where one would have to do [:a][a+1:b][b+1:c] to have the border perfectly. That terrible?
Even though one could see a ≤ x < b to be more adept to 0-base, and a ≤ x ≤ b to be more adept to 1-base, the way I see it, index base and slicing rules could be somehow independent. And one would index and slice the way it would fit the rationale of the problem or the data, because even slicing a 1-base indexed array with a ≤ x < b, would still produce an expected outcome, as in cir=[1,2,3,4,5] so that cir[1:3]=[1,2] or cir[:3]=[1,2]. Same thing applying a ≤ x ≤ b to a 0-base indexed array, as in rul[0,1,2,3,4,5] so that rul[:2]=[0,1,2] or rul[0:2]=[0,1,2].
Given that python is an example of human friendly code language, emphasizing readability, wouldn't having 0 and 1 base indexing and custom slicing methods, improve the thought process when writing and reading the code, by fitting them better to specific contexts or data? Is there some language that provides both or each language picks only one?
Cheers
On Sun, Mar 22, 2015 at 3:38 AM, pedro santos probiner@gmail.com wrote:
Why can't both 0-base and 1-base indexing exist in the same language, and why can't slicing be customized?
Pedro,
The best answer ever is by one of the most important computer scientists of the 20th century, Edsger W. Dijkstra -- who was also Dutch, like Guido van Rossum:
https://www.cs.utexas.edu/users/EWD/ewd08xx/EWD831.PDF
The answer is also visually beautiful, as are all Dijkstra's manuscripts. Some font designer should create a font based on Dijkstra's handwriting.
Cheers,
Luciano
If I'm indexing the ruler marks, intervals, boundaries, dots, makes sense to start of at 0; rul=[0,1,2,3,4,5,6] would index every mark on my ruler so that accordingly rul[0]=0, rul[5]=5. If I'm indexing the blue circles, natural number quantities, objects, spans, makes sense to start at 1; cir= [1,2,3,4,5] so that cir[1]=1 and cir[5]=5.
Now, a lot of the discussion was to do with slicing coupled with the indexing and I don't totally understand why.
a ≤ x < b is not so intuitive when dealing with objects ("I want balls 1 up to the the one before 3"), so on one side, you put the finger on what you want and on the other, on what you don't want. But this method does have the neat property of producing neighbor selections that border perfectly, as in [:a][a:b][b:c]. Although in inverse order(-1), the results can be unexpected as it returns values off-by-one from its counterpart like; L=[0,1,2,3,4,5] so that L[1:3]=[1,2] and L[3:1:-1]=[3:2]. So it's consistent with the rule a ≤ x < b, grabbing the lower limit item, but it can feel strange by not producing the same selection with inverse order.
a ≤ x ≤ b is a natural way to select objets ("I want the balls 1 up to 3"), so you're putting the finger on the things you want. If you inverse the order(-1) it's still very easy to grasp what are you picking because whatever you select it's included like: L=[0,1,2,3,4,5] so that L[1:3]=[1,2,3] and L[3:1:-1]=[3,2,1]. Problems seem to arrive though, when trying to do neighbor selections, where one would have to do [:a][a+1:b][b+1:c] to have the border perfectly. That terrible?
Even though one could see a ≤ x < b to be more adept to 0-base, and a ≤ x ≤ b to be more adept to 1-base, the way I see it, index base and slicing rules could be somehow independent. And one would index and slice the way it would fit the rationale of the problem or the data, because even slicing a 1-base indexed array with a ≤ x < b, would still produce an expected outcome, as in cir=[1,2,3,4,5] so that cir[1:3]=[1,2] or cir[:3]=[1,2]. Same thing applying a ≤ x ≤ b to a 0-base indexed array, as in rul[0,1,2,3,4,5] so that rul[:2]=[0,1,2] or rul[0:2]=[0,1,2].
Given that python is an example of human friendly code language, emphasizing readability, wouldn't having 0 and 1 base indexing and custom slicing methods, improve the thought process when writing and reading the code, by fitting them better to specific contexts or data? Is there some language that provides both or each language picks only one?
Cheers
-- ________________________________
Pedro Alpiarça dos Santos Animator 3DModeler Illustrator
Python-ideas mailing list Python-ideas@python.org https://mail.python.org/mailman/listinfo/python-ideas Code of Conduct: http://python.org/psf/codeofconduct/
Luciano Ramalho luciano@ramalho.org writes:
The best answer ever is by one of the most important computer scientists of the 20th century, Edsger W. Dijkstra -- who was also Dutch, like Guido van Rossum:
Fascinatingly – to me, at least – Dijkstra's orthography for parenthetic en dash is the opposite of that Tim Peters used in the thirteenth aphorism of the Zen of Python.
Dijkstra, EWD831:
Exclusion of the lower bound –as in a) and b)– forces […]
Peters, Zen of Python:
There should be one– and preferably only one –obvious way to do it.
How wonderful to see another dimension of combinations for that style issue, in a Dijkstra paper talking about exploring the dimensions of another style issue :-)
Hey
In one of my projects I'm stuck in an environment where there are multiple co-existing coding environments, one of which has a convention of using 0 based indexing and the other using 1 based indexing. All i can say is that is is a VERY (i cant possibly emphasize this enough) bad idea. it is an unending source of confusion and off by 1 bugs.
It is like the line endings issue all over again ... CR or LF and then you end up with CR, LF and CR LF, choosing 1 is definitely better than choosing both. Python got this right, please do not inflict this upon the python community!
I got real life experience with this and i'm telling you this is a disaster waiting to happen, please don't..
On 22 March 2015 at 09:24, Luciano Ramalho luciano@ramalho.org wrote:
On Sun, Mar 22, 2015 at 3:38 AM, pedro santos probiner@gmail.com wrote:
Why can't both 0-base and 1-base indexing exist in the same language,
and why can't slicing be customized?
Pedro,
The best answer ever is by one of the most important computer scientists of the 20th century, Edsger W. Dijkstra -- who was also Dutch, like Guido van Rossum:
https://www.cs.utexas.edu/users/EWD/ewd08xx/EWD831.PDF
The answer is also visually beautiful, as are all Dijkstra's manuscripts. Some font designer should create a font based on Dijkstra's handwriting.
Cheers,
Luciano
If I'm indexing the ruler marks, intervals, boundaries, dots, makes
sense to start of at 0; rul=[0,1,2,3,4,5,6] would index every mark on my ruler so that accordingly rul[0]=0, rul[5]=5.
If I'm indexing the blue circles, natural number quantities, objects,
spans, makes sense to start at 1; cir= [1,2,3,4,5] so that cir[1]=1 and cir[5]=5.
Now, a lot of the discussion was to do with slicing coupled with the
indexing and I don't totally understand why.
a ≤ x < b is not so intuitive when dealing with objects ("I want balls 1
up to the the one before 3"), so on one side, you put the finger on what you want and on the other, on what you don't want. But this method does have the neat property of producing neighbor selections that border perfectly, as in [:a][a:b][b:c]. Although in inverse order(-1), the results can be unexpected as it returns values off-by-one from its counterpart like; L=[0,1,2,3,4,5] so that L[1:3]=[1,2] and L[3:1:-1]=[3:2]. So it's consistent with the rule a ≤ x < b, grabbing the lower limit item, but it can feel strange by not producing the same selection with inverse order.
a ≤ x ≤ b is a natural way to select objets ("I want the balls 1 up to
3"), so you're putting the finger on the things you want. If you inverse the order(-1) it's still very easy to grasp what are you picking because whatever you select it's included like: L=[0,1,2,3,4,5] so that L[1:3]=[1,2,3] and L[3:1:-1]=[3,2,1]. Problems seem to arrive though, when trying to do neighbor selections, where one would have to do [:a][a+1:b][b+1:c] to have the border perfectly. That terrible?
Even though one could see a ≤ x < b to be more adept to 0-base, and a ≤
x ≤ b to be more adept to 1-base, the way I see it, index base and slicing rules could be somehow independent. And one would index and slice the way it would fit the rationale of the problem or the data, because even slicing a 1-base indexed array with a ≤ x < b, would still produce an expected outcome, as in cir=[1,2,3,4,5] so that cir[1:3]=[1,2] or cir[:3]=[1,2].
Same thing applying a ≤ x ≤ b to a 0-base indexed array, as in
rul[0,1,2,3,4,5] so that rul[:2]=[0,1,2] or rul[0:2]=[0,1,2].
Given that python is an example of human friendly code language,
emphasizing readability, wouldn't having 0 and 1 base indexing and custom slicing methods, improve the thought process when writing and reading the code, by fitting them better to specific contexts or data?
Is there some language that provides both or each language picks only
one?
Cheers
-- ________________________________
Pedro Alpiarça dos Santos Animator 3DModeler Illustrator
Python-ideas mailing list Python-ideas@python.org https://mail.python.org/mailman/listinfo/python-ideas Code of Conduct: http://python.org/psf/codeofconduct/
-- Luciano Ramalho | Author of Fluent Python (O'Reilly, 2015) | http://shop.oreilly.com/product/0636920032519.do | Professor em: http://python.pro.br | Twitter: @ramalhoorg _______________________________________________ Python-ideas mailing list Python-ideas@python.org https://mail.python.org/mailman/listinfo/python-ideas Code of Conduct: http://python.org/psf/codeofconduct/
On Sun, Mar 22, 2015 at 5:38 PM, pedro santos probiner@gmail.com wrote:
a ≤ x < b is not so intuitive when dealing with objects ("I want balls 1 up to the the one before 3"), so on one side, you put the finger on what you want and on the other, on what you don't want. But this method does have the neat property of producing neighbor selections that border perfectly, as in [:a][a:b][b:c]. Although in inverse order(-1), the results can be unexpected as it returns values off-by-one from its counterpart like; L=[0,1,2,3,4,5] so that L[1:3]=[1,2] and L[3:1:-1]=[3:2]. So it's consistent with the rule a ≤ x < b, grabbing the lower limit item, but it can feel strange by not producing the same selection with inverse order.
a ≤ x ≤ b is a natural way to select objets ("I want the balls 1 up to 3"), so you're putting the finger on the things you want. If you inverse the order(-1) it's still very easy to grasp what are you picking because whatever you select it's included like: L=[0,1,2,3,4,5] so that L[1:3]=[1,2,3] and L[3:1:-1]=[3,2,1]. Problems seem to arrive though, when trying to do neighbor selections, where one would have to do [:a][a+1:b][b+1:c] to have the border perfectly. That terrible?
To add to what other people have said in support of Python's indexing style, I'd like to point out one situation where fully-closed ranges are used: Scripture references. Have a look at this page:
https://www.biblegateway.com/passage/?search=Mark+3&version=NIV
This is one chapter from the Bible. Passages within that chapter can be identified by starting and ending verse, inclusive at both ends. So, for instance, the paragraph under the heading "Jesus Appoints the Twelve" would be Mark 3:13-19. Note how the end point is actually one less than the number that starts the next passage. Python identifies the boundaries between elements, which corresponds perfectly to a numbering system such as this; noting the passage as "Mark 3:13-20" would mean you start reading at the indicator for verse 13, and stop reading as soon as you reach the indicator for verse 20, which makes a lot more sense.
Obviously it's way WAY too hard to change something as extensively used as Bible references - the backward incompatibility concern is just too strong - but this may give some indication of why it's more sensible to work with half-open ranges. A half-open range also gives a convenient notation for "to the end of the chapter": instead of "Mark 3:20-3:35", it would simply be "Mark 3:20-4:1". (Chapters and verses are numbered from one, not zero, but in an ideal world, this would also change, so it would be "3:19-4:0".)
ChrisA
On 03/22/2015 10:30 AM, Chris Angelico wrote:
To add to what other people have said in support of Python's indexing style, I'd like to point out one situation where fully-closed ranges are used: Scripture references.
While indexing and slicing use natural numbers, the advantage of the half open interval becomes more obvious if you consider examples with real numbers.
When using a closed range interval with real numbers ...
n1 <= i <= n2 ? <= i <= n3
Picking the start value for the next adjacent sequence is not simply a matter of adding 1.
The half open sequence makes that case both trivial and elegant.
n1 <= i < n2 n2 <= i < n3
And it works just as well with natural numbers. And works best if the end value is a multiple of the step value.
As to weather to use 0 or 1 indexing, 0 indexing is very useful for interfacing with the hardware. 0 is a valid memory address, and the 0th bit is the first bit of a byte. Indexing at that level directly correspond to how the hardware is built. For other higher level things, ones indexing can work equally well, (in my opinion), we just don't want to mix them.
0 <= i < n # n equals number of items
1 <= i < n + 1 # Dijkstra prefers the first case.
But consider in programming, the indexes are frequently variables rather than literals.
start <= i < start + count
This works in both cases. In the above case of zero indexing it's really.
0 <= i < 0 + n
It just happens that it can be simplified a bit in the case where there start value is zero. And then the end index becomes the count, but only when the start index is zero.
When ones indexing is used, the zero index can be used to specify the end value when stepping towards zero from both directions.
When zero indexing is used. it allows for wrap around behaviour when the index crosses zero. Sometimes that can be very nice.
A reason a language should choose one or the other, and not both, is that the choice defines how many other things interact with that choice. Trying to do both can mean having two versions of many functions and statements.
Cheers, Ron
The strongest proof that mixed index bases are a bad idea is that this is a valid statement in VB6:
Dim array(1 to 10) as Integer
For all X, if VB6 allows X, then X is a bad idea. :-)
*Newbie slowly steps down from the table*
I guess then 1-indexing in most cases the it's something relegated to fleshing, so that the index offset is done on the user level and not at the code level. Yes because no one will pick a gambling dice with face 0 :P I guess it's a matter of brain education... I did fell I needed to run a bunch of tests just to re-assure myself about the 1-indexed problem being solved with a 0-base representation. But I totally understand the arguments presented here as code consistency also makes it more malleable and somewhat more black-boxy. As someone that deals a lot with vectors with linear color workflows I know that what could be a clean work environment can be become a minefield of conversion routines that add an overhead to the brain when trying to operate Frankenstein operations into data flow setups.
Thanks for the extra discussion, especially when indexing was addressed separately from slicing routines.
Cheers
On Sun, Mar 22, 2015 at 7:52 PM, David Mertz mertz@gnosis.cx wrote:
The strongest proof that mixed index bases are a bad idea is that this is a valid statement in VB6:
Dim array(1 to 10) as Integer
For all X, if VB6 allows X, then X is a bad idea. :-)
-- Keeping medicines from the bloodstreams of the sick; food from the bellies of the hungry; books from the hands of the uneducated; technology from the underdeveloped; and putting advocates of freedom in prisons. Intellectual property is to the 21st century what the slave trade was to the 16th.
Python-ideas mailing list Python-ideas@python.org https://mail.python.org/mailman/listinfo/python-ideas Code of Conduct: http://python.org/psf/codeofconduct/
Your first example is 0-based even though it's closed (L[1:3]=[1,2,3]), which weakens your whole argument for 1-based indexing. and makes me think such a possibility might actually confuse you--which is exactly why we don't have it.
As you say, it may still make sense to have closed ranges and slices alongside half-open, even with 0-based indices. And many newer languages do that, often by using ".." vs. "...", which seems to be pretty readable. But there's no obvious way to add something similar to Python at this point. (Also, I think the fact that ranges and slices are different things with different syntax is a benefit of Python, not a deficit, and it's even harder to design a good solution without losing that benefit...)
Sent from my iPhone
On Mar 21, 2015, at 11:38 PM, pedro santos probiner@gmail.com wrote:
Hi
I'm an Art and CG student learning Python and today's exercise was about positions in a tiled room. The fact that I had to check if a position was inside the room and given that in a 1x1 room, 0.0 was considered in and 1.0 was considered out, it kept me thinking about 0-base indexing iterables and slicing.
Read some articles and discussions, some pros and cons to each 0-base and 1-base, concerns about slicing, etc. But ultimately the question that got stuck in me and didn't found an answer was: Why can't both 0-base and 1-base indexing exist in the same language, and why can't slicing be customized?
If I'm indexing the ruler marks, intervals, boundaries, dots, makes sense to start of at 0; rul=[0,1,2,3,4,5,6] would index every mark on my ruler so that accordingly rul[0]=0, rul[5]=5. If I'm indexing the blue circles, natural number quantities, objects, spans, makes sense to start at 1; cir= [1,2,3,4,5] so that cir[1]=1 and cir[5]=5.
Now, a lot of the discussion was to do with slicing coupled with the indexing and I don't totally understand why.
a ≤ x < b is not so intuitive when dealing with objects ("I want balls 1 up to the the one before 3"), so on one side, you put the finger on what you want and on the other, on what you don't want. But this method does have the neat property of producing neighbor selections that border perfectly, as in [:a][a:b][b:c]. Although in inverse order(-1), the results can be unexpected as it returns values off-by-one from its counterpart like; L=[0,1,2,3,4,5] so that L[1:3]=[1,2] and L[3:1:-1]=[3:2]. So it's consistent with the rule a ≤ x < b, grabbing the lower limit item, but it can feel strange by not producing the same selection with inverse order.
a ≤ x ≤ b is a natural way to select objets ("I want the balls 1 up to 3"), so you're putting the finger on the things you want. If you inverse the order(-1) it's still very easy to grasp what are you picking because whatever you select it's included like: L=[0,1,2,3,4,5] so that L[1:3]=[1,2,3] and L[3:1:-1]=[3,2,1]. Problems seem to arrive though, when trying to do neighbor selections, where one would have to do [:a][a+1:b][b+1:c] to have the border perfectly. That terrible?
Even though one could see a ≤ x < b to be more adept to 0-base, and a ≤ x ≤ b to be more adept to 1-base, the way I see it, index base and slicing rules could be somehow independent. And one would index and slice the way it would fit the rationale of the problem or the data, because even slicing a 1-base indexed array with a ≤ x < b, would still produce an expected outcome, as in cir=[1,2,3,4,5] so that cir[1:3]=[1,2] or cir[:3]=[1,2]. Same thing applying a ≤ x ≤ b to a 0-base indexed array, as in rul[0,1,2,3,4,5] so that rul[:2]=[0,1,2] or rul[0:2]=[0,1,2].
Given that python is an example of human friendly code language, emphasizing readability, wouldn't having 0 and 1 base indexing and custom slicing methods, improve the thought process when writing and reading the code, by fitting them better to specific contexts or data? Is there some language that provides both or each language picks only one?
Cheers
--
Pedro Alpiarça dos Santos Animator 3DModeler Illustrator
Python-ideas mailing list Python-ideas@python.org https://mail.python.org/mailman/listinfo/python-ideas Code of Conduct: http://python.org/psf/codeofconduct/