28 ms·
Again on 0-based vs. 1-based indexing
- nabla9 6y agoJust like big- vs. little endian issue, the differences matter less than everyone adopting one. When you program having two code sets with different base of indexing is several times worse than either alone. 0-based indexing is here. 1-based has no benefit. New languages should use 0-based indexing.
- Buttons840 6y agoI'm pretty sure 1-based indexing is here too. Should new languages use it? Fortran was using 1-based indexing 15 years before C existed if I understand correctly?
- ModernMech 6y agoYes! And it's not a coincidence Fortran was conceived to target scientists, while C was targeting kernel developers. The target audience had much to do with the choice.
- goerz 6y agoFortran predates C, so 1-based indexing has been “here” arguably longer than 0-based indexing. Most languages targeted at numerical computing use 1-based indexing because mathematics uses 1-based indexing in linear algebra. That seems like a huge benefit to me! C has 0-based indexing precisely because it doesn’t have genuine multi-dimensional arrays and has to use pointer arithmetics instead (which in my opinion makes it a very bad fit for scientific computing)
- Aardwolf 6y agoMathematicians can, and do, use both, and would arguably be better of with 0-based. Mathematicians sometimes need to use partitioned matrices, and describing the start and end indices of those partitions goes better with 0-based indexing of matrix elements, so that the top left element is at 0,0. It's horrible if you have to work with such things in 1-index based matlab, the amount of nested +1 and -1 corrections you need to type...
- kgwgk 6y ago0-based indexing was "here" long before C was created. Lisp or Algol are more or less contemporary to Fortran. The former uses 0-based indexing, the latter can use arbitrary bounds. As does Fortran at least since the seventies, by the way.
- NotAnOtter 6y agoThis is where I land. Anyone arguing one way or the other tends to make up some arbitrary reason or impose assumptions on the implementation of the language. They are both perfectly fine and logical numbering systems, however since 95% of developers expect a 0-based numbering system, that is what we should use.
- ModernMech 6y agoThis ignores the fact that people use different languages for different purposes. More people use Excel, which is 1-based, than all other languages combined. Should Excel be 0-based because people who use C (a much smaller minority) prefer their language to be 0-based?
- jonathanstrange 6y agoI like Ada's indexing range types, if you do it the right way your arrays can be 0-index or 1-index or indexed from 23 to 149. The bottomline is that in a good language it shouldn't matter and the programmer shouldn't even know how the compiler indexes the data. You iterate from array'first to array'last. I do prefer 0-based indexing, of course, but often using indices can and should be avoided anyway.
- henrikeh 6y agoOr indexed by any discrete type with a defined order, including enums and negative numbers. The latter being quite useful for signal processing. Another thing to the add to the list of good ideas in Ada everyone ought to copy.
- bvrmn 6y agoAda ranges are closed intervals and need +1/-1 tweaks to handle a set of ranges.
- laichzeit0 6y agoIt's also funny that a new language like Julia chose to go the 1-based route. https://github.com/JuliaLang/julia/issues/558 https://github.com/JuliaLang/julia/issues/558 It seems clearly the motivation was to be in line with other mathematical languages. But then time and again I see people say Julia is supposed to replace Python in the future. Well, you've just set yourself up for a little fight there because I'd say the vast majority of programmers are used to 0-based by default, and they're not going to dick around and install packages and crap to change that default behaviour, least of all when trying to be convinced that some new language is superior.
- recursive 6y agoLinking to Dijkstra does not have to be an appeal to authority. I happen to find his position to be persuasive on its own merits.
- IlliOnato 6y agoI don't have a strong position on 0-based versus 1-based, but Dijkstra's argument does not make any sense to me. He says that expressions A ≤ x ≤ B, A < x ≤ B, and A < x < B are confusing and a source of errors, but A ≤ x < B is not. I really cannot understand what's the difference, and why one would be more mentally taxing than another. (From that he concludes that iterating over 0-based array is more intuitive. This kinda/sorta makes sense, if you believe the initial premise). I'd like someone to shed light on this, if possible.
- silon42 6y agoOne interesting case is when partitioning on integers, but wish to compare with floats... How do you get all values in say in 0..9.9999 when using 0 <= x <= 9... it makes sense to use 0 <= x < 10... Another case is when using datetime... how do you specify the whole day without knowing the precision of your datetime (seconds, milliseconds, nanoseconds...)... again, specifying 2021-01-10 to 2021-01-11 makes more sense than using 2021-01-10T23:59:59.999 for the upper boundary.
- lifthrasiir 6y ago> How do you get all values in say in 0..9.9999 when using 0 <= x <= 9... it makes sense to use 0 <= x < 10... This breaks down for negatives, though. -9.9999..0 would be -10 < x <= 0.
- mjevans 6y agoIt's just fine for negatives. If you slide the range that 'makes sense' back by 10 (add -10 to it): -10 <= x < 0 This excludes the end of the range, it includes the start of the range. What's changed is that the start of the range is no longer at zero and also has crossed from positive to negative.
- molecule 6y agoThis was submitted yesterday [0], w/ discussion today. - [0] https://news.ycombinator.com/item?id=25829966 https://news.ycombinator.com/item?id=25829966
- raverbashing 6y agoWell yes, Python or js don't have pointer arithmetic but underneath that's what happens if you're dealing with an array Zero indexing might look weird at first but I think it helps in most cases.
- IlliOnato 6y agoHelps how?
- raverbashing 6y agoWrapping around the array, you just need for your position to be i%len Though ok, reading an array backwards requires a len-1-i
- IlliOnato 6y agoWhy would you need to "wrap around" an array? I guess it's helpful if you use an array to represent a cyclic group, but how often this happens in practice? And when you need the number of the last element, you need to do A[n-1], which is "less helpful", I guess.
- raverbashing 6y agoI think both those cases happen with a certain frequency, yes, your last element is a bit trickier, though in Python it is represented by A[-1] (so that would turn into A[len-1]) Yeah, maybe there's no fundamental advantage, one would have to check the most common cases. > Why would you need to "wrap around" an array? Ring buffers
- secondcoming 6y agoRingbuffers are used all over
- hmry 6y agoOr alternatively, len + ~i Okay, maybe don't use that one in production :)
- kstenerud 6y agoI was hoping for an interesting analysis of 0 vs 1 based indexing, but instead got a 3 page rant of HN-this and appeal-to-authority-that which adds absolutely nothing of value to the discussion. It feels more like a bottom-of-the-page angry comment to an article than an actual article.
- codefreakxff 6y agoFully agree. Got to the end of the post and was looking for the rest. The ranting could have been fine if there was more information and exploration. As it is, it’s unremarkable and not worth reading
- NotAnOtter 6y agoThis is probably because this whole debate is pedantic and irrelevant. 0-base wins, at this point it's not about picking a fork in the road, just swimming up stream for the sake of standing out. LUA is over 23 years old at this point, it made a arbitrary design decision and has had to die on that hill ever since.
- anonymoushn 6y agoIt looks like LUA is only 7 years old: https://github.com/mniip/LUA https://github.com/mniip/LUA
- omnicognate 6y agoThat copyright comment doesn't say Lua is 7 years old and I don't see how you could interpret it as such. Lua is generally considered to have been created in 1993: https://en.m.wikipedia.org/wiki/Lua_(programming_language) https://en.m.wikipedia.org/wiki/Lua_(programming_language)
- catwell 6y agoYou didn't get the joke. Hint: case matters (and look at that repo :p).
- waiseristy 6y agoI think it just comes down to where you want your index-out-of-range errors to occur. Pretty much any language I can think of inits primitives with all bits set to 0. So either, you accidentally forget to set your index vars to 1 and out-of-range it there, or accidentally forget to take away 1 when accessing the end of the array. Pick your poison
- foerbert 6y agoI don't think it simplifies quite that far. There are languages that are capable of catching such errors ahead of time. Now that I think about it, there are even more that catch the initialization error - or at least do so more automatically than the end point error.
- IlliOnato 6y agoPerl initializes its scalars to "undef", not 0. If you try to use undef as an array index, it will convert it to 0 but issue a warning. I'd prefer it to be an error instead.
- deleted 6y ago[deleted]
- grawprog 6y agoFor a general purpose programming language 1-based indexing probably causes more confusion and errors than benefits. A language trying to be a general purpose computer programming language shouldn't abstract in a way that's likely to lead to confusion with those that understand the fundamentals. For a domain specific language focused around simulating physical things, or a specific application, 1-based indexing may be the more appropriate option. In this case, abstracting the problem domain is likely more important than adhering to the limitations of hardware.
- foerbert 6y agoI don't think it's a real fundamental though - at least not for computing in general. It is true for C, and it is likely true for the many languages that implement things like C. But it's not inherently true that the 'fundamental' implementation of an array must exist as a C array does.
- grawprog 6y agoI don't know if it relies on C so much but what C is an abstraction over. An array in C is a set of data that exists in consecutive locations in memory. Memory addresses start at 0. Technically, a C array located at the start of addressable memory, by the nature of the way we've decided computers work in general, would start at 0. Plus as many extra zeros as your architecture can represent. This is generally the way computers are assumed to work. Higher level general purpose programming languages exist primarily to serve as an abstraction over the fundamental architecture of computers. C is technically a higher level language than machine code and assembly code, both of which use the 'lowest address is zero' abstraction. Every other abstraction, including C exists over top of that. My point is mostly, if you're trying to remain relatively close to abstracting over general computing keeping arrays and their index based on what they are fundamentally abstracting over makes sense. In domain specific applications, it may make less sense.
- saagarjha 6y ago> Memory addresses start at 0. That's just another convention, though…
- oconnor663 6y agoHas this argument been rehashed much: If you use 1-based indexing, you can't iterate over a list of maximum length with a simple loop. The normal loop condition is `while i < len` (0 based) or `while i <= len` (1 based). If len is maximal, the second one probably has an overflow bug in the loop body that turns it into an infinite loop or a crash.
- thaumasiotes 6y agoA list of length equal to whatever maxint is is something you would have to set up on purpose. (If it were naturally occurring and unpredictable, then you would need to handle the much more common case where the length of the list is greater than maxint, too.) The fact that a weird situation you set up intentionally needs special-purpose handling doesn't seem odd or unreasonable to me.
- naniwaduni 6y agoThis is actually symmetrical. When you use 0-based indexing, you can't count down with a simple loop: you need to either extend your index type to include an invalid -1 or apply the infamous evaluate-then-decrement semantic. In practice, this means people often index with a signed integer, which is absurd. And lest you think that counting down is unnatural—there are quite a few advantages in comparing to zero on every iteration instead of a computed upper bound, like that you can often roll the condition check in with the decrement instead of having to do a separate comparison.
- oconnor663 6y agoAh that's a very good point.
- ufo 6y agoI'd also argue that counting down is more common than having a list with UINT_MAX elements.
- donatj 6y agoI grew up on languages that were 1 indexed - BASIC, VB, VB.Net. It took me a long time to get used to 0 indexed, primarily in college and later in working with more C inspired languages, yet I think 0 indexed is superior. Why? Numbers in programming start at 0, even in the languages with 1 indexing. Period. When I initialize an integer, unless I explicitly set a value, it’s 0. From a purely pragmatic standpoint, making the first number an invalid location in a list just adds unnecessary complexity and increases the odds of off-by-one errors. On the same token, there’s nearly no benefit to starting at one.
- IlliOnato 6y agoNo, no "period". There are plenty of languages that either require you to initialize your variables, don't allow to use a variable until it's initialized, or give an uninitialized variable a special value like "undef" or "Nil". I agree that BASIC is inconsistent, but there are many languages beyond Basic and its descendants... I'm afraid your argument still sounds like "C does it, so it is right" mentality.
- secondcoming 6y agoI'm pretty sure that VB is/was 0-based, but that was controllable per-module via Option Base https://docs.microsoft.com/en-us/previous-versions/visualstudio/visual-basic-6/aa266179(v=vs.60)?redirectedfrom=MSDN https://docs.microsoft.com/en-us/previous-versions/visualstu...
- klyrs 6y agoPython supports -1 based indexing, so clearly that's the superior convention.
- irjustin 6y agoNo it doesn't. That just gives you the last element, which is not a "based indexing". JavaScript will allow arr[-1] as an "individual" element, but it's internally an object and so iterating and hoping that -1 comes in order doesn't work.
- silon42 6y ago> No it doesn't. That just gives you the last element, which is not a "based indexing". I never liked that feature, it has chance to hide bugs in more complicated code where indexes are calculated... I'd prefer a 'reverse' indexer instead.
- klyrs 6y agoSure it does. -2 gives second to last, -3 gives third to last, etc. If you only use negative indices i, the "base" of the array is the end, and arr[i] is just arr[len(arr)+i].
- irjustin 6y agoHow does that fall within the definition of "base index"? that's just array position referencing. You can't even create an array/list in python w/o a hard 0 reference.
- klyrs 6y agoFirst, it's a "joke", second, nobody is going to force you to use non-negative indices. Sure, you can use a base index of zero and read left to right... but you can use a base index of -1 and read right to left and live a full (if lonely) life without considering the passé alternatives. More precisely, I'm defining the "base" to be the right hand side of the array and operating on the reversed list -- it's just a change of variables. Python supports -1 based indexing, but does not support 1 based indexing. You could easily define a language which only provides the -1 based indexing but does not support 0-based. Let me demonstrate: void *malloc_r(int size, int count) { void *m = malloc(size, count+1; m[count] = count; return m+count; } void free_r(void *m) { free(m - m[0]); } Memory allocated through malloc_r is right-aligned and you should only use negative indices. Best not touch m[0]!
- gabereiser 6y agoHere’s some fuel to the flames: < is less chars than <= , it also is more logical. 0-based indexes have the advantage of if in comparison and range. Mathematics treats 0 as special and can have all sorts of side effects if dropped into a formula, code doesn’t have this side effect (unless running formula as an algorithm, which is math). To save yourself from headaches, I believe 0-based indexes are preferred in almost every modern language for the simple reason of optimization. I have no evidence to back this. NULL=Nothing=0 is a thing though.
- chmod775 6y agoHere's two arguments arguments in favor of 0-based 'indexing' (or offsets), that aren't just "because that's how it's done": 1. It is faster. Due to how memory works, 1-based languages need to subtract 1 internally every time you access an array[1]. 2. It works mathematically better with some of the most common operations on array offsets, like modulo and division into round/ceil/floor. You'll be peppering your code with +1 or -1 around those a lot if you use 1-based indexing. [1]: This is lua, for instance: https://github.com/lua/lua/blob/master/ltable.c#L702 https://github.com/lua/lua/blob/master/ltable.c#L702
- anand-bala 6y ago(On the phone so forgive the possible typos) I am not sure (1) is a very convincing argument. The subtraction of 1 internally is not necessarily gonna be there once the code gets compiled. I will personally concede with you on (2), but it's still not very convincing considering that Fortran (a 1-index language) is still (arguably) the most popular language for linear algebra. Personally, I feel "The Index Wars" are the same as the "Text Editor Wars": a matter for personal opinion.
- chmod775 6y ago>I am not sure (1) is a very convincing argument. The subtraction of 1 internally is not necessarily gonna be there once the code gets compiled. Theoretically one can optimize it - though only when one can statically infer the index and the compiler decides to inline the array access function. If you can't do that, the best you can hope for is a fast CPU instruction like LEA or something. In theory one could make a lot of things fast, in practice they rarely are, and it's always better to avoid problems now than to pray later.
- stabbles 6y agoOh come one now, don't be silly. Think about vectorization and loop unrolling. It _always_ does a memory load with an offset as a single CPU instruction. As an example a 4 times unrolled sum of doubles on AVX looks like this: L64: vaddpd ymm0, ymm0, ymmword ptr [rcx + 8*rsi] vaddpd ymm1, ymm1, ymmword ptr [rcx + 8*rsi + 32] vaddpd ymm2, ymm2, ymmword ptr [rcx + 8*rsi + 64] vaddpd ymm3, ymm3, ymmword ptr [rcx + 8*rsi + 96] add rsi, 16 cmp rdx, rsi jne L64 The `rcx + 8*rsi + 32` stuff is offsets the compiler generates. Don't even think about worrying about -1 here...
- rufflez 6y agoWhy is this a thing?? Seriously, every language has its rules...just follow the rules and build something useful
- gnulinux 6y agoThis type of bikeshedding behavior is a sign of technical immaturity. The more technical experience one gains, one usually becomes a lot more disinterested about small syntactic technical details of programming languages and more interested about larger abstract concepts (e.g. discussions on Monads, type theory, "everything is an expr" etc...)
- pwdisswordfish5 6y agoZero- versus one-based indexing actually matters somewhat for correctness. The real trivial ‘small syntactic technical’ bikeshedding is braces versus indentation (and: which kind of indentation) or semicolons versus no semicolons.
- marcosdumay 6y agoSemicolons vs. end of line (like in Python) has a significant difference on what kinds of things you can express. End of line based syntax strongly discorages long lines, what brings problems and benefits. (And the Javascript choice is simply wrong.) Semicolons vs. indentation structure (like in Haskell) has a huge usability difference in interactive shell. It's trivial on editor code. The dismissal of syntax as trivial is not a good line of thinking. Syntax tends to have surprising impacts on semantics.
- tester34 6y agoyeye, "HN" tends to abstract everything to the point that sometimes I do wonder how Java is not the church language of HN, also I do wonder whether people here still write code, or just became "architects". So, there's nothing wrong with challenging common norms - remember NULL? XML oriented programming?
- syntaxing 6y agoThe biggest thing about index 0 or 1 is the inclusive and exclusive slicing. When the index is 0 and the slicing is [inclusive:exclusive], I find it a bit easier to write code with array manipulation.
- je42 6y agosometimes i program in Lua (which is 1-based) but mainly i write code in 0-based languages. The worst is really when you switch between the languages, but after a while you get used to it. You just need to watch out like a hawk, when calculating the index of the last element ;)
- IlliOnato 6y agoWhile I don't have a strong preference in this "war", I can think of an interesting argument for 1-based. Our time counting is 1-based. There is no zeroth second, zeroth minute, hour, day, month, year, or century. This actually makes it slightly harder in 0-based languages to work with time and dates. Also, it might be an indication that 1-based system is somewhat more intuitive to non-programmers.
- flukus 6y ago> There is no zeroth second, zeroth minute, hour, day, month, year, or century. No there isn't, but we still use 0 to denote the first minute of an hour, just as we use 0 to denote the first element of an array.
- wraptile 6y agoOur counting is 0-based as well - usually when you start by saying "one" it is implied that 1 second has elapsed. So while we don't pronounce zero we still count starting from it.
- hmry 6y ago> There is no zeroth second, zeroth minute, hour My clocks all start at 00:00:00 every day, and that seems entirely logical to me. It's also how all programming languages that I've worked with represent time.
- IlliOnato 6y ago
- tsegratis 6y agoWhat convinced me is graphs' zero origin When counting apples (i.e. only +) then 1 based. but when (* % ^ √ ÷) then 0 based
- ajuc 6y agoTBH indexing became much less important with every language adopting some sort of "for all" and map/filter/reduce constructs. If you don't care about indexes you don't need to think about them (finally!). The remaining cases are by definition edge cases and warrant enough attention that bugs caused by 1- vs 0-based indexing doesn't seem to be a big problem in practice. It's like with goto and structured programming - people stopped using goto for loops and ifs, so the remaining cases where goto is used as last resort aren't much of a problem. People think hard before doing this.
- sicher 6y agoYes. I did write Lua for a few years and have a hard time remembering seeing any indexing cases. I probably encountered some but they were very few and far between.
- jsinai 6y agoExactly. When I was a beginner I made off-by-1 errors (in Python mind you) all the time. Now that I iterate directly through arrays or use map-reduce patterns I rarely have to handle the index itself.
- cycomanic 6y agoI disagree, this depends a lot on your problem space. I mainly do scientific programming and so have to do array/vector slicing etc. and indexing definitely plays a big role.
- Blikkentrekker 6y agoDo you often find a need to slice hardcoded numbers, however? I find that the only hardcoded number I often need to slice or index is indeed the start, and most languages do offer something for that such as `slice[..i]` to slice from the start.
- cycomanic 6y agoWell I was replying to the statement that the OP was saying indexing is less important and I find when dealing with slices it definitely is important (as can be seen in your example). Generally, I agree with what someone else here stated, 1 or 0 based indexing is less important than open or closed interval. The discussion around these two is typically mixed because 1-indexing uses right-open interval while 0-based indexing uses right-closed.
- oivey 6y agoIn the same way that I don’t think learning sklearn is the hard part of knowing ML, I don’t think 0 or 1 -based arrays is the hard part of any particular language. There are situations where both are appropriate. The choice of either as the deal breaker for a language is extremely superficial.
- tragomaskhalos 6y agoOne thing I would hope there is consensus on is that 1-based indexing is easier to learn. My son is doing Python at school, and the "first-element-is-actually-element-zero" is something that has to be dinned into them, a sure sign that it is non-intuitive. In similar vein, as adult programmers we know that the half-open range is the most useful mechanism for expressing a sequence, but again we have to explain to kids that if they want the numbers 1 to 12 (eg to do a times table program) they must type range(1,13), which at that stage of their learning just seems bizarre. Actually I could go on at length about why Python is a terrible teaching language, but I'll stop there !
- dragonwriter 6y agoHonestly, the problem is that we don't distinguish cardinal from ordinal numbers in programming As an offset (which is cardinal—how far something is from a starting point) or really any cardinal use, zero is the natural starring point. For ordinals, “1st” is the natural starring point. But we don't write “1st” in programming, even when we used 1-based indexing to try to match an ordinal intuition, we just write “1”. If we distiguished ordinals and allowed both cardinal offsets and ordinal indexes to be used, I think we’d be fine.
- adrian_b 6y ago"1st" is not a "natural" choice for the starting point of ordinal numbers. If anything, it is an artificial choice, because in programming it is derived from a property of most, probably of all, human languages that have ordinal numerals. In most, probably in all, human languages the ordinal numerals are derived from the cardinal numerals through the intermediate of the counting sequence 1, 2, 3, ... When cardinal numbers appeared, their initial use was only to communicate how many elements are in a set, which was established by counting 1, 2, 3, ... Later people realized that they can refer to an element of a sequence by using the number reached at that element when counting the elements of the sequence, so the ordinal numerals appeared, being derived from the cardinals by applying some modifier. So any discussion about whether 1 is more natural than 0 as the starting index goes back to whether 1 is more natural as the starting point of the counting sequence. All human languages have words for expressing zero as the number of elements of a set, but the speakers of ancient languages did not consider 0 as a number, mainly because it was not obtained by counting. There was no need to count the elements of an empty set, you just looked at it and it was obvious that the number was 0. Counting with the traditional sequence can be interpreted as looking at the sequence in front of you, pointing at the right of an element and saying how many elements are at the left of your hand, then moving your hand one position to the right. It is equally possible to count by looking at the sequence in front of you, pointing at the left of an element and saying how many elements are at the left of your hand, then moving your hand one position to the right. In the second variant, the counting sequence becomes 0, 1, 2, 3, ... The human languages do not use the second variant for 2 reasons, one reason is that zero was not perceived as having the same nature as the other cardinal numbers and the other reason is that the second variant has 1 extra step, which is not needed, because when looking at a set with 1 element, it is obvious that the number of elements is 1, without counting. So neither 0 or 1 is a more "natural" choice for starting counting, but 1 is more economical when the counting is done by humans. When the counting is done by machines, 0 as the starting point is slightly more economical, because it can be simpler to initialize all the bits or digits of an electronic or mechanical counter to the same value for 0, than initializing them to different values, for 1. While 1 was a more economical choice for humans counting sheep, 0 is a choice that is always slightly simpler, both for hardware and software implementations and for programmers, who are less likely to do "off by one" errors when using 0-based indices, because many index-computing formulas, especially in multi-dimensional arrays, become a little simpler. In conclusion, the choice between 0 and 1 never has anything to do with "naturalness", but it should always be based on efficiency and simplicity. I prefer 0, even if I have programmed for many years in 1-based languages, like Fortran & Basic, before first using the 0-based C and the other languages influenced by it.
- dmcg 6y agoThis reminds me that because array access is just addition, in C you can also write 2[a] to access the third element of a.
- kevin_thibedeau 6y agoWith 1-based indexing, you can't index the last element of an array that occupies the entire domain of the index type.
- kzrdude 6y agoYou can't represent the length of that same array in the domain, which is normally enough to make this scenario unusable.
- gliptic 6y agoNot always, I've used bytes to store indexes to arrays of 256 elements. The length doesn't have to be the same narrow type as the indexes.
- josephg 6y agoSo? With 0-based indexing, the length of an array falls outside the domain of the index type. The number of times either of these properties has mattered for me also cannot be represented in the domain of 1-based indexes.
- deleted 6y ago[deleted]
- ChrisSD 6y agoPrevious discussion: https://news.ycombinator.com/item?id=25829966 https://news.ycombinator.com/item?id=25829966
- tincholio 6y agoI kinda take issue with his complaining about referring to Dijkstra's argument as being an argument from authority. Dijkstra makes a pretty solid case in his writing, it's not just about him being Dijkstra.
- josephg 6y agoBut we don't need to rely on Dijkstra's opinion at all. Plenty of us have programmed with both 1-based and 0-based languages and (most of us) will tell you that it doesn't really make much of a difference in practice. It (generally) doesn't change how you conceptualize your program or how you express it to the computer. Its like tabs and spaces - pick one, life is too short to care. Async vs threads matters more. Cargo vs NPM vs pip matters more. Practically speaking programming lua, do/end instead of {} took me longer to get used to than 1-based indexing.
- renox 6y ago> (most of us) will tell you that it doesn't really make much of a difference in practice. I disagree, I had to slice bitfields in Ethernet packets in Lua and I hated 1-based indexing very much! IMHO languages should either have 0-based indexing or any-index (as Ada does) unless you really wants to be a "mathematic only language" which is why I think that it's OK for Julia to be 1-based but not OK for Lua.
- deleted 6y ago[deleted]
- user-the-name 6y agoIt doesn't make a difference if all you use arrays for is to keep a list of items and to iterate over those items. But if you do anything more advanced with arrays, then you will start to notice the difference.
- josephg 6y agoCan you give some examples?
- samatman 6y ago0-based indexing with closed intervals is better for slicing. This shouldn't be controversial. It's because you can represent a zero interval cleanly: [3,3) is an empty interval after slot 2, representing a single cell is [3,4). This has two nice properties. One is that two slices are adjacent if the beginning and ends match, and the other, far more important, is that the length of the slice is end - start. That's the one that really gets us something. It means you can do relatively complex offset math, without having to think about when you need to add or subtract an additional 1 to get your result. I use Lua every day, and work with abstract syntax trees. I mess this up all. the. time. Of course you can use closed intervals and stick with 1-based indexing. But for why you shouldn't, I'm going to Appeal To Authority: read Djikstra, and follow up with these. https://wiki.c2.com/?WhyNumberingShouldStartAtZero https://wiki.c2.com/?WhyNumberingShouldStartAtZero https://wiki.c2.com/?WhyNumberingShouldStartAtOne https://wiki.c2.com/?WhyNumberingShouldStartAtOne https://wiki.c2.com/?ZeroAndOneBasedIndexes https://wiki.c2.com/?ZeroAndOneBasedIndexes
- WA 6y agoTrue, but there are examples where 1-based indexing is easier, like returning the last element based on length. I think array[array.length] is easier to understand than array[array.length - 1]. Or the predecessor of the last element: array[array.length - 2] makes you think, whereas array[array.length - 1] is more obvious.
- robertlagrant 6y agoThis is why Python has negative indices :) Then it's just my_list[-1] or my_list[-2].
- steerablesafe 6y ago> It really shows how conditioned an entire community can be when they find the statement “given a list x, the first item in x is x[1], the second item in x is x[2]” to be unnatural. It's not unnatural, but it's not natural either. It's just that 1-based indexing aligns with natural language conventions better. It also matches with some math conventions for matrices and vectors, but those don't have to use 1-based indexing either to work. I learned linear algebra with abstract "index sets" (I), where I can be {1, 2, 3, .., n}, {x,y,z}, {0,1,2}, whatever. Programming in 0-based indexing means way less +-1 adjustments on boundaries. Division/modulus also works way better with 0-based indexing, so flattening multi-dimensional arrays is more easily expressed too. In the end it's just a convention, it shouldn't matter too much. My money is still on 0-based indexing, as it lends itself to less errors and cognitive load when you get used to it. I used both extensively. Tangential: conventions that are more "natural" are usually not actually natural, but just align themselves to other conventions better. Of course it's always good if conventions align, but sometimes it's inconsequential. Also there are situations where we can't make all conventions align. An other little pet-peeve of mine is people calling big-endian more natural than little-endian, where there are actually different competing conventions: 1. Usual way of printing memory content from lower address to higher address from left to right (think hexdump). 2. Usual way of writing down numbers from left to right from most significant digit to least significant digit. 3. Expressing the value of the number from the byte array elements (\sum_0^(width-1) byte[n] 256^n for little-endian, \sum_0^(width-1) byte[n] 256^(width-n-1) for big-endian) Big-endian aligns better with the combination of 1 and 2. Little-endian aligns better with 3.
- threatofrain 6y ago> It's just that 1-based indexing aligns with natural language conventions better. What about how Europeans index their building floors from 0?
- robertlagrant 6y agoOr what number does a stopwatch start from?
- lifthrasiir 6y agoDo not add any more fuel to the flame and instead use 2-based indexing: https://github.com/simonster/TwoBasedIndexing.jl https://github.com/simonster/TwoBasedIndexing.jl Seriously, the exact value of the lower bound for indexing doesn't matter here (some algorithms are best described with the lower bound other than 0 or 1, for example). The fixed or preferred lower bound is the real problem. Any argument for/against 0-based and 1-based indexing tends to gloss over the real problem because those arguments only exist to make some languages look better than other languages. As we move away from forced explicit indexing (e.g. arr.first() or foreach instead of arr[$LBOUND] or `for (i=$LBOUND; ...)`), it becomes clear that there is no such thing like the preferred lower bound for sequences at all.
- epage 6y ago> Do not add any more fuel to the flame and instead use 2-based indexing: https://github.com/simonster/TwoBasedIndexing.jl https://github.com/simonster/TwoBasedIndexing.jl This reminds me of my last company where the answer to the 2 vs 4 space debate was 3 spaces.
- corysama 6y ago“Should array indices start at 0 or 1? My compromise of 0.5 was rejected without, I thought, proper consideration.” — Stan Kelly-Bootle
- ufo 6y agoFun fact: Hisham, the author of the blog post we're discussing is a notorious user of 3 space indentation. It actually works quite well in Lua, where blocks are terminated by the "end" keyword. Still sacrilegious if you ask me though :)
- enriquto 6y agoIt does not seem like a big deal, both conventions are easy to understand and natural to use. Except if you work with the discrete Fourier transform. Then 1-based indexing is extremely cumbersome and annoying. More generally, if your indices are to be understood "modulo N", it makes sense that they are all strictly smaller than N (or even signed, and centered around 0).
- jpttsn 6y agoA newborn is not one year old. Midnight is not 01:01 AM.
- nkurz 6y ago> A newborn is not one year old. Similar to the indexing question, this is only true for some cultures: "East Asian age reckoning originated in China and continues in limited use there along with Japan and Vietnam, and is still common in Korea. People are born at the age of one..." https://en.wikipedia.org/wiki/East_Asian_age_reckoning https://en.wikipedia.org/wiki/East_Asian_age_reckoning
- GolDDranks 6y ago> It really shows how conditioned an entire community can be when they find the statement “given a list x, the first item in x is x[1], the second item in x is x[2]” to be unnatural. It really shows how conditioned the mankind is that they call the "0th" ordinal number by the name "first". We have never moved past the phase where the concept of "zero" was heretic. Here + offset makes SO much sense. I think we should move to use it in other contexts too. "0 steps from the start of an ordered list" "1 step from the start of an ordered list" etc. At the moment we are using two different "scales" for measuring things and labeling orders. We could as well use the letters "A", "B", "C" for the latter, and it wouldn't change a thing. Hindsight is 20/20, but it's just a confusing mishap that we are using "numbers" and "numbers + 1" for the two purposes, where the second one could be expressed just as another "measurement", and we could get rid of the confusing "numbers + 1" scale.
- simiones 6y ago> they call the "0th" ordinal number by the name "first". We have never moved past the phase where the concept of "zero" was heretic. Even in maths it's pretty bad, because the Natural numbers still sometimes don't include 0, so that the 0th Natural number is 1, the 1th natural number is 2 etc. (using 1th instead of 1st to avoid the confusing nature of "first" in this discussion).
- threatofrain 6y agoI believe it's far more typical to include 0 for the naturals than not, and it's trending that way too.
- scoutt 6y ago> It really shows how conditioned the mankind is that they call the "0th" ordinal number by the name "first". Well, every component of mankind was born. At birth your "first" year of life is the "0th" year. Right now, everyone is living its "n+1"th year of life (n >= 0). I think the influence is strong, other than natural.
- qayxc 6y agoHehe - cracks me up every time. This is a left-over from mathematics where indices are distinct from the abelian group of integers. So the index "1" as used to refer to vector element for example, is different from the number "1" on the number line. That is, one is an element of an index set comprised of ordinal numbers, while the other is an element of the integers. The confusing part is, that both use the same symbol when in actuality they represent different concepts. The integer "1" is just a number like √2 or -7. The ordinal "1", however, is the representation of the concept "first". The ordinal "0" would, if used as an index, always yield the empty set as a result (see von Neumann ordinals), which wouldn't be particularly useful in a programming language. The mapping that selects elements given an index is arbitrary and can be defined as necessary. This allows for constructs like "x[-1]" mapping to the last element of an array. Here, "1" still means the "first" element, but the sign indicates the negative direction, i.e. start from last element. In short: there's an argument to be made for having two distinct versions. One (1-based indexing) is consistent with mathematics, while the other (0-based indexing) is consistent with low-level low-level data representation and makes no distinction between ordinals and integers.
- robertlagrant 6y agoRebutting the dismissal of offsets as an artefact of an old language: - pointer offsets - the article seems to dismiss these, but they're used loads in systems/network/driver programming, which is a reasonable chunk of the most important programming - conceptual offsets - e.g. time of day starts at zero, not one. We think in this way a lot, and it's useful.
- bayindirh 6y agoWhile I think these debates healthy (when they're civil and well grounded), found out that I don't have any preferences for one over other for things like array indexing. Every language has its own design decisions based on some requirement or opinion, and while I have rather strong preferences about languages, these kind of design decisions doesn't strike any nerves. As long as it's usable, that's fine by me.
- gabordemooij 6y agoCitrine is also 1-indexed (https://citrine-lang.org/#lists https://citrine-lang.org/#lists), I think this would help people who are not developers to read and possibly verify code a bit easier. Of course it is just a small step, but I feel code in general is drifting away from the normal users, who seems to be confine to graphical interfaces. Wasn't it an objective once in the software development community to try and make code as accessible as possible?
- numlock86 6y ago> Again on 0-based vs. 1-based indexing The problem is within the phrasing and its premise: Are you using an index or an offset? 99% of the time I think of an offset, so "first" makes sense as "0". If you go by indexing "1" suddenly makes sense as an index. When people say index in the context of arrays or data structures usually they mean an offset. To me it's simply wrong phrasing.
- pwdisswordfish5 6y agoI don’t know why 1-based-indexing supporters insist on pointing out this distinction. Whenever one indexes some kind of a map with numbers – and it actually matters that they are numbers that you can perform arithmetic on, not just opaque symbols – chances are they will be computed from an ‘offset’ somewhere or vice versa, which means the notions are going to blend a lot.
- tobr 6y agoI don’t have any experience working with 1-based indexing, but it seems reasonable. I certainly remember how confusing 0-based indexing felt for a long time when I first learned to program. On the other hand, I’ve made an observation about timelines in music production software, where bars are counted starting from 1. As you zoom out, only every 4th bar tends to be labeled, which creates this strange sequence: 1, 5, 9, 13, 17… I always found that incredibly hard to reason about, and perhaps it would have been a better idea to label the first bar as 0.
- kangalioo 6y agoExactly. There's tons of little annoyances that arise from 1-based indexing. Working on software projects about data analysis or similar makes this crystal clear. 0-based indexing may not be natural for human society, but it very much is natural for calculations and operations on data - exactly what programming languages are meant to do.
- giantDinosaur 6y agoAnd look how annoying it is that we didn't have a year 0: 2001 was the start of the 21st century. How horrible is that!
- zgs 6y agoThe crazy part is that Lua accepts "array[0]" just fine and it works exactly as expected. This is a non-issue in Lua but many people cite it as a problem.
- Hitton 6y agoUntil Perl v5.30 it was possible to set how you would index with "$[" variable.
- midjji 6y agoAn interesting perspective is what this does to pointers in terms of unsigned representation, effectively making 0 a special case which could be used for null. But in practical terms it would just limit 32 bit systems to 31 bits of adressable memory, or make pointer arithmetics wierd. The latter isnt that much of a problem, as its only when pointers are basic types it matters, and free pointer arithmetics is a mistake whose only advantage is compiler speed, not even application speed. For instance, even in slicing, [start:end) eliminates this issue. Though there is something to be said for verbosity. I think this becomes an argument for 0 based indexing, but a case could be made to the opposite. That said, consistency is what is valuable, so the only truly wrong answer would be the one we use in real life.
- DanielBMarkham 6y agoDisclaimer: I don't care about this argument one way or another. However I found the author missed the point (as perhaps many commenters did?) "...nowadays, all arguments that say that indexes should be 0-based are actually arguments that offsets are 0-based, indexes are offsets, therefore indexes should be 0-based. That’s a circular argument..." Yes, that is a circular argument. It's not the one I would use. C made the decision that indexes and pointers are the same thing. It's a logical argument and one that's not circular. If they're separate things, then yes, you end up in a circle. For languages that are not C-like, you could argue "pick an idiom and stick with it across multiple languages" or "make programming languages easier for humans to understand" Both of those arguments are preferential arguments. Perhaps there could be a study comparing the merits of each, but I haven't seen one yet. I like chocolate ice cream. I like making pointers and arrays as similar as possible. I like being able to collapse pointer arithmetic down. I like doing huge mallocs and then playing around with large, empty hunks of memory. Some folks don't. I get it. Code should look like the way we think about the problem. That's an ideal state we'll never reach, but it's worthy of continued discussion.
- codeflo 6y ago> offsets are 0-based, indexes are offsets, therefore indexes should be 0-based You might dispute the premises, but I don’t see the circle. Isn’t this just “men are mortal, Socrates is a man, therefore Socrates is mortal”?
- rrobukef 6y agoIt's missing 'since indexes are 0-based, they're offsets". Edit: if I would make this argument, I'd say the assumption that indexes are offsets is baseless. This is easily proven since there are languages where this isn't true. However I would argue the problem based on practical merits: the reason there no 1-based index op-code exists is because no dominant programming language has 1-based indexing. Which is a self-fulfilling prophesy.
- DanielBMarkham 6y agoI didn't want to go there, but yes. If I had called that out, it would lead to a discussion about just what is meant by the term "offset". Defined broadly enough, the point worked for the author. In general, I try to find the most general point and rebuttal as possible. These discussions tend to dive into pedantry and semantics. I'm just trying to do my part to engage the author where they are. ymmv
- axismundi 6y agoMaybe we should be counting from zero in general? https://lasvegassun.com/news/2016/nov/07/the-human-calculator-is-fixed-on-helping-young-peo/ https://lasvegassun.com/news/2016/nov/07/the-human-calculato...
- nathias 6y agoAre there any languages with reversed indexing, or some other more bizzare options?
- cookie_monsta 6y agoCounting in binary gets pretty boring if you have to start from 1.
- cycomanic 6y agoThe funny thing is that even in natural language we don't use base 1 or 0 consistently. For example why is the 1st of January the first day of the month/year, but your first birthday is when you turn one year old, i.e. when your first year of life finishes.
- whalesalad 6y agoThis is a true hacker mindset. Love the fact that the author is questioning the groupthink here in a constructive way.
- emn13 6y agoI had a ROFL moment when he discredited appeals to authority, and then progressed to note that it's conventional math notation - which is pretty much the same kind of logic. Furthermore, mathematical notation is almost universally terrible. It's inconsistent, ambiguous, and has many undeclared dialects. Oh, and many people use 0-based index to boot, because, you know, whether that's conventional or convenient (largely orthogonal qualities alas in math) depends on the context. I mean, I can sort of buy his argument that it's arbitrary, but then he also points out that there's at least one advantage to 0-based indexing, namely that works well in offset based scenarios (not just for pointers). So in which case is 1-based indexing convenient? Based on this blog post, never.
- deleted 6y ago[deleted]
- stkdump 6y agoWhile 1-based index is probably easier to learn and understand for a beginner, even as a beginner there is quickly an overhead where you have to adjust indices by 1 all the time as soon as you do any math on indices. Going from Basic to C was hard for me for many reasons, but a lot of complexity in my code that I took for granted just vanished. This truly showed me the power in getting such fundamental choices right.
- nathell 6y agoWacław Sierpiński (1882–1969), the namesake of Sierpiński's triangle, was famously a proponent of zero-based indexing, including in everyday life. Sadly, I can only find sources in Polish that corroborate this [0]. [0]: https://wyborcza.pl/AkcjeSpecjalne/7,160474,24501452,zaczynali-od-zera-stali-sie-legenda-jak-warszawscy-matematycy.html https://wyborcza.pl/AkcjeSpecjalne/7,160474,24501452,zaczyna...
- ben509 6y ago0-based indexing is preferable because the mathematics of half-open intervals make composing ranges far simpler. It becomes a bit more obvious as soon as you do any kind of non-integer ranges, because you find that only integers have a reliable "subtract one" operation. For instance, suppose you're doing a lot of date arithmetic, and you might include times. If I have a range: [2005-05-05, 2007-07-07) This unambiguously includes all times. If I compose it: [2005-05-05, 2007-07-07) [2007-07-07, 2008-08-08) If I shift all of them forward 10 days: [2005-05-15, 2007-07-17) [2007-07-17, 2008-08-18) Every possible time within the new range is accounted for. Transformations on the ranges are obviously correct. If we can't agree on whether time resolves to seconds, milliseconds or nanoseconds, it doesn't matter. That's because you can find the beginning and end of a range without knowing how to subtract by one. If you later decide to add times, it will just work because, conceptually, you already handle every possible value in the range. If you want to construct a series of ranges of floats, it's a bad idea to do [3.457, 6.799999], [6.8, 12.47699999]. If you use half-open intervals, it just works, without mucking with the end of the range. This is the reason that "indices are offsets" is powerful: it's not circular reasoning, but a simplification because we're removing an unnecessary primitive (subtracct 1) that only reliably works with integers. And to bring this back to integer offsets, even when you're working strictly with integers, you may want to conceptually work with rational numbers. When you're working out your math for buffered IO, you need to map byte indices to chunk indices. You need to assign every byte written to a chunk. In a 0-based world, your chunk offset is simply your byte offset / chunk length. Because there is no distinction between indices and offsets, it's a clean mapping between one offset scheme and the other. It means you can work out on paper when a new chunk should be started, and then translate that into integer arithmetic. And your code directly reflects the math, rather than having to stick "- 1" and "+ 1" in here and there.
- ginko 6y agoOne issue I see with 1-based indexing is that it makes x[0] undefined, so even if you pass an unsigned integer index to a function you need to verify that it's != 0 before you use it. So in a way it'd be the whole null pointer thing for array indices all over again. Another minor issue is that you can access one less element with a fixed size integer than when you do 0-based indexing. So for u8 you can only access 255 elements instead of 256 for instance.
- pwdisswordfish5 6y agoThis is an argument about checked indexing, not about where indexing should start; after all, whatever the index base, you still need to check that the index fits within the bounds of the array. It doesn’t matter if a behaviour is technically deterministic and defined if it’s not what you want to happen. I mean, just read the explanation of the ‘wat’ talk: <https://stackoverflow.com/a/9033306/3840170 https://stackoverflow.com/a/9033306/3840170>. Every one of these behaviours is defined by the ECMAScript standard, but they’re still useless.
- adrian_b 6y agoYes, but checked indexing requires only one comparison with the upper limit when your indices are 0-based, instead of 2 comparisons, when the starting index is different from 0. The sign of the index can be determined without a comparison, usually simultaneously with one of the previous operations.
- lrossi 6y agoActually, in Lua, which caused the original discussion, it’s legal to use x[0], since the language doesn’t distinguish between arrays and dictionaries (Lua calls them tables). But if you do that, the length calculation will be off by one. I have seen some difficult to debug issues caused by this when I used to work on game scripts.
- mjevans 6y agoThat sounds like an implementation bug in the name of speed or memory size rather than a programming correctness bug. What's the correct behavior if the 'table' doesn't have any integers as keys, but instead other elements such as strings?
- mhandley 6y agoFor things that wrap, such as ring buffer indices or packet sequence numbers in a fixed-size field or clocks (hour of the day, minutes in an hour), zero-based indexing is simple modular arithmetic. Wrapping of one-based indices can of course be done, but it's more complicated than necessary.
- OscarCunningham 6y agoOn the other hand, actual clocks have a 12 on them.
- jibbit 6y agoErlang is kinda interesting.. 1-based, but you might never need to know that.
- LandR 6y agoIt's range that gets me all the time, some make the end inclusive, some exclusive. Clojure (range 1 10) ;=> (1 2 3 4 5 6 7 8 9) C# Enumerable.Range(1, 10).PrintAll(); 1 2 3 4 5 6 7 8 9 10 Ruby (1..10).each { |n| puts n } #=> 1 2 3 4 5 6 7 8 9 10 Python for i in range(1, 10): print(i, end=', ') => 1 2 3 4 5 6 7 8 9
- teekert 6y ago"... of course, nowadays the number one reason is tradition and familiarity given other popular languages, and I think even proponents of 0-based indexing would agree, in spite of the fact that most of them wouldn’t even notice that they don’t call it a number zero reason." That's it, I'm switching to saying number 0 reason from now on. If you are talking about your number 1 reason, I will forever be wondering what your number 0 reason would be. I'll tell my wife tonight she is my number 0!
- Yizahi 6y agoEven worse is sometimes this 0-based numbering is carried over to a world of enumerable things, cargo cult like. In my project we have multiple physical entities which have numbers, e.g. blades, ports, channels on so on, all of them are counted from 0 because some genius decided to write that into standard. And now there are multiple points in the code where 1-based numbers are converted into 0-based and back, and incredibly - there are bugs there :) . Talking to humans gets equally weird and confusing when you are talking about second port numbered 1, it's just never gets natural, even after years working on these devices.
- sfgweilr4f 6y agoWell... I wrote a snake game in python and lua. 0 based array (python) : screen_pos = x + y * width 1 based (lua) : screen_pos = 1 + x + y * width shrug So 0 based seems to work a little better for arithmetic based array references. But really you'll never resolve this to perfection. Assembly language programmers are very unlikely appreciative of 1-based. Its all about what you're comfortable with. Those wanting pointers can imagine a base address added to each calculation. 1-based then needs a -1... which is then a strange thing to advocate for.
- taneq 6y agoWe can't even agree on this for floors of buildings. Half the world starts at 'G' then 1, 2, 3 etc. as you go upwards, the other half starts at 1, then 2, 3 etc. And then you have Japan which sometimes starts at 2F. Hey, maybe we should use 2-based indexing.
- FabHK 6y agoI like the ground floor to be G=0. Then basement floors can be -1, -2 etc., and it is (y-x) floors to go from floor x to y.
- snarfy 6y agoIndexes start at 1. Offsets start at 0. They are different things.
- klik99 6y agoThe harder it is to learn, the more it takes you to change your mind. It's hard to see things without bringing baggage Also, the irony of complaining about HN holy wars becoming just another trigger to continue! I'll do my part - whichever side you are on - you are wrong.
- mannykannot 6y agoI am pretty sure that the last, counterfactual, paragraph of this article is spot-on. Personally, I am not so much interested in which way is more right, but which way is less likely to result in off-by-one and related errors, though I do not know how you could gather data on that, other for people beginning programming, and any difference might go away or even flip as programmers gain experience and move on to more difficult problems. (Of course, the most effective solution is to not use indexing at all, except where absolutely necessary.)
- epage 6y ago> You see, Lua uses 1-based indexing, and lots of programmers claimed this is unnatural because “every other language out there” uses 0-based indexing. > I’ll brush aside quickly the fact that this is not true — 1-based indexing has a long history, all the way from Fortran, COBOL, Pascal, Ada, Smalltalk, etc. — and I’ll grant that the vast majority of popular languages in the industry nowadays are 0-based. So, let’s avoid the popularity contest and address the claim that 0-based indexing is “inherently better”, or worse, “more natural”. Maybe I missed the comments about 1-indexing being "unnatural" but if the author is referring to the discussion I took part in, then this is a strawman. It wasn't about what was "natural" or "unnatural" but about people switching from their primary language to secondary languages and gotchas like 1-indexing being error prone. We had a platform team at my last company looking to adopt Lua for client customization. The primary authors became familiar with Lua in writing the code logic but everyone else would be touching their part, or contributing back to the core, not as people familiar with Lua but as C++ developers who would be blindly making changes in another language. It felt similar to maintenance of our Perl scripts. You don't brush up and become an expert on a language you interact with on a yearly cadence. It is important in these cases to have few gotchas to make casual contributions easier and safer. This says nothing about using 1-indexing when your target audience isn't 0-indexed programmers (speaking of those who choose to use Lua and not to Lua's creators). Unfortunately, for me, even with my complaints (this and language compatibility), I'll probably still use Lua for some projects of mine. I've looked at others and I'm mainly concerned about the community size.
- Decabytes 6y agoAs weird as I find 1 based indexing(looking at you R) I still get confused by 0 based indexing. This happens all the time when I’m working in pandas and thinking about line numbers in the file vs the data frame, and I recently had an issue with this while implementing Conway’s Game of Life in Racket, while I was traversing the array and when I was looking for neighbors. It has been enough of an issue for me to seriously reconsider my stance on indexing
- hhyndman 6y agoThe APL language has this system variable ⎕IO (called QUAD IO -- index origin), which could be set to 0 (for 0-based indexing) or 1 globally in the environment. Also, ⎕IO can be set as a local variable of a function to limit the scope of the indexing origin, which made it convenient to simplify the code to implement certain algorithms.
- tromp 6y agoThe first element being at index 0 feels as natural as 0 being the first natural number. Or let me rephrase that in the interest of avoiding natural language bias. The starting element being at index 0 feels as natural as 0 being the starting natural number.
- DonaldFisk 6y agoPascal, contrary to what the article states, allows any subrange of integer as an array index. For example, kernel: array[-3..3,-3..3] of real; is a 7x7 array. It has negative indices, e.g. x := kernel[-3,-3]; See https://www.tutorialspoint.com/pascal/pascal_arrays.htm https://www.tutorialspoint.com/pascal/pascal_arrays.htm Sometimes you want negative indices, e.g. when performing a convolution on an image with a kernel.
- pmeira 6y agoTo complement, dynamic arrays ("array of ...") are always 0-based in Delphi and Free Pascal. This was apparently introduced in Delphi 4 (1998).
- PaulHoule 6y agoThis is why in languages like pascal or Ada you can make an array that runs from 7 to 35.
- fpoling 6y agoAfter some experience with Go I realized that in quite a few cases it will be nice to have 1-based indexes. If one have a variable that is an index into an array, then it is natural to initialize it to an invalid index like -1. But in Go everything is initialized by default to 0. So to get -1 one needs extra code. With one-based indexes zero would be a very natural invalid value as an index similar to a null pointer.
- mjevans 6y agoExpress a slice of length 0, backed by a buffer of length 1024 elements.
- albrewer 6y agoI never thought I'd say this, but you've got to give props to VB where you can declare the starting (and ending) index of your array to be whatever you want!
- TuringTest 6y agoMystery solved 0 1 2 3 4 5 v v v v v v |---|---|---|---|---|---... ^ ^ ^ ^ ^ ^ 1 2 3 4 5 6...
- thayne 6y agoThere are many situations where 1-based indexing is more natural. There are also many situations where 0-based indexing is more natural. And also many (possibly most?) situations, where it doesn't really matter. My 2 cents: it isn't really that important. As long as the developer is aware of whether the language they are currently using 0 or 1 based indexing.
- pwdisswordfish5 6y agohttps://xkcd.com/774/ https://xkcd.com/774/
- ubriewbaduk 6y agoI'd say from a mathematical perspective, 0-based indexing makes more sense, simply because the Peano axioms start with 0 for the natural numbers. Also, thinking of overflows makes more sense this way, because it's just modular arithmetic.
- metreo 6y agoUnfortunately off-by-one errors can be insidious and non-obvious to debug, having different systems only complicates this. 0-indexing makes sense for systems and computer programming while 1-indexing makes translating math more straightforward. Inter-converting between the two systems is unfortunately non-trivial, even if the cost isn't that high.
- psychoslave 6y agoHonestly, I feel like `some_list.first` is the most ergonomic. And if the API provides `second`, `third`, `antepenultimate`, `penultimate`, and `last` methods it covers a large part of what one most often use. Past third rank, then I will feel better served with a `slice` method, whose documentation provides explicitly it’s index convention, whether it makes a modulo on out of bounds, etc.
- daemonk 6y agoThis is something that's extremely annoying to deal with in a genomics context. Various formats in the field uses 0-based or 1-based and inclusive or exclusive.
- tzs 6y agoIn mathematics, both are common. For example, when working with polynomials or polynomial-like things, it is common to label coefficients starting with 0. E.g., a0 + a1 x + a2 x^2 + ... The subscript on the coefficient then matches the power of x, letting you write the general term as ai x^i, which works out great when using capital sigma notation. One the other hand, matrix rows and columns usually start from 1, so the elements on the top row are usually a11, a12, a13, ..., and the next row is a21, a22, a23, ..., and so on. In an attempt to bring some unity to the two sides on this issue in programming, let me offer something that I'm sure everybody will be able to agree on. Once upon a time I was implementing some mathematical code in C++. It was a mix of things from places where mathematicians would number from 0 and where they would number from 1. I decided that the code would be clearer if the code looked like the formulas in the math papers they came from, which meant I wanted to use 0-based arrays in some places and 1-based in others. Solution: I overloaded the () operator so that array(i) was a reference to array[i-1]. Then I could use 0-based or 1-based, depending on whether I was using a formula that came from a 0-based or 1-based area of mathematics. Everybody agree that this was not a good idea?
- dodobirdlord 6y agoJulia and Fortran, languages designed to be used for mathematics and high performance scientific computing, take a similar approach in the language itself and support arbitrary starting indices for arrays. Sometimes the math is just cleaner when the index starts at 0, or 1, or 2, or -1! https://docs.julialang.org/en/v1/devdocs/offset-arrays/ https://docs.julialang.org/en/v1/devdocs/offset-arrays/
- petschge 6y agoAnd of course there is C++ libraries to do the same. For example the blitz++ library. Negative indices to the left of element[0] are great for ghost zones in codes that do domain decomposition over different MPI ranks.
- Acur 6y agoJulia (normally 1-based), Polynomials package: julia> using Polynomials julia> p = Polynomial([1, 0, 2]) Polynomial(1 + 2*x^2) julia> p[0] 1 As long as it is domain specific and wrapped in custom types I don't really see an issue.
- mangecoeur 6y agoHonestly 0-based indexing is one of the most annoying things to teach. In sciences, people really don't care about programming arcana: I have never found anyone who found 0-based indexing natural or intuitive. In fact, much of the vehemence in favor of it seem to be more about programmer shibboleths, to make some people feel they are in a special 'in-the-know' club (certainly if the r/programmerhumour reddit is anything to go by). All I can do for scientists is tell them the advantage of learning a programming language outweighs the weirdness.
- jlg23 6y ago> I have never found anyone who found 0-based indexing natural or intuitive. It is pretty intuitive when thinking about natural numbers as steps along a path. Then, zero is the number that means "you are already there".
- mangecoeur 6y agojust... no. We are not talking about a number line here, we are talking about array indexing. That is a list of things that you count starting from the beginning. Like, no one lines up their children and says 'here is my Zeroth child'. There is a reason that Fortran, which was designed for science and engineering, uses 1 based indexing: because it makes sense when counting things, as opposed to dealing with some internal arcana of a computer's memory model.
- eterevsky 6y agoI don't understand why the author treats referring to Dijkstra's paper as "appealing to authority". To me it is natural to defer to a well-written paper instead of repeating the same arguments in your own words, regardless on who wrote it.
- xirbeosbwo1234 6y agoI find zero-based indexing more natural. Consider the case of dates. Dates are naturally one-indexed. There is no year zero. This means that the 21st century started in the year 2001. Likewise, the current decade started under a month ago, not over a year ago. If you think the 21st century started in the year 2000, as do most people, then that implies that the first century either started in the year 1 B.C. (ugly) or was only 99 years long (not a century). People naturally (and incorrectly) default to zero-based indexing in this case! I would go farther and make centuries zero-indexed too. It's far more natural to say that the Nth century is everything in the form Nxx than to say it's (N-1)xx. Every time I run across a numbered century I have to stop and think for a split second to calculate what years it covers. I got this wrong on several occasions in grade school and was marked down for it. Zero-based indexing works naturally for grouping things. One-based indexing does not. This, of course, doesn't matter much.
- dnautics 6y agoThis is obviously spaces vs tabs third rail in PL design, but riffing off of the language in the article, probably we should all agree on two opinions: 0-based indexing is inherently better for machines. 1-based indexing is inherently more natural for humans. ** For a short stint I was running a (small) datacenter, and despite being an apologist for 1-indexed programming languages, I zero indexed EVERYTHING in the datacenter. Let me just say, that was a huge mistake. Physical items are not offsets. Even though I was then working in a 0-indexed PL, The amount of contortion I had to do to remember zero indexing made the likelihood of errors higher (I did not make any that weren't quickly recoverable, but still).
- randomdata 6y ago> 1-based indexing is inherently more natural for humans. Depends on what you are indexing. Time, for example, is very commonly represented as being 0-based by humans.
- dnautics 6y agoSure, to the point where it's confusing when it's not (no year 0 e.g.)
- randomdata 6y agoMy culture uses 0-based ages, where in your first year on earth you are 0 years old and turn 1 after you have been alive for an entire year, but I am not sure age would be any more confusing if it were 1-based. I don't see anything fundamental there. Other cultures do use 1-based ages (you are 1 on the day you are born) and they seem to get along just fine. Whatever you are accustomed to is what seems natural.
- xxs 6y agoI have experience with 1-based indexes: basic/pascal. My 2nd language after basic was assembler. Off-by-1 bugs were plenty and confusing - mixing assembly with basic and pascal. Zero based with Java/Javascipt has felt a lot more natural than one based. Likely in 20y+ years there has not been an-off-by-1 bug. With that said: 0 based has felt totally fine and natural. All it takes to remember: inclusive/exclusive.
- jkingsbery 6y agoI know Visual Basic gets a bad rap, but as a learning language it had an interesting feature, `Option Base`. By putting `Option Base` in a module, it changed how the indexing of arrays worked. It defaulted to 0, but for some applications (and also, when you're first learning), 1 can be convenient. Of course, there are problems with this in a professional setting, such as how do you enforce uniformity across modules, and what happens if you copy code from one module that's Base 0 to one that's Base 1 and vice versa. But when I was first learning how to program, it was helpful to me to have a language that allowed for some choice. In the meantime, 23 years of programming have led me to believe that index base 0 makes sense. For many applications it's moot, because we should be using higher level functions (like map and reduce) for processing lists. In every other application (such as working with data on a grid), dealing with offsets does make things easier. Perhaps the convention is arbitrary. But, lots of industries have arbitrary conventions that we all agree on just to aid communication, and I disagree with the original author that the term "groupthink" applies in this situation.
- zzo38computer 6y agoMy own opinion is that zero based indexing is generally much more useful, and makes a lot of things things simpler and/or more sensible mathematically or otherwise. However, there are some cases where an index based on some other number (often, but not necessarily, 1) is more useful. (Some programming languages, such as BASIC, allow you to define whatever starting index that you want to do.)
- ltbarcly3 6y agoI don't know if one is somehow 'essentially' better, but 0 based indexing have clearly won as a convention.
- madhadron 6y agoI settled on 0 based indexing as the right way to go when I was doing this calculation: https://madhadron.com/posts/2009-07-17-determining-affine-transforms-from-three-points.html https://madhadron.com/posts/2009-07-17-determining-affine-tr... When you start calculating offsets and transformations of coordinates, starting at 1 forces you to carry around extra additive constants everywhere.
- pasquinelli 6y agoi don't really care if the language has me start counting indices at 0 or 1. it's never been the part of the problem of programming that has caused me significant trouble.
- GuB-42 6y agoMaybe the confusion comes from the fact that programming languages don't make a distinction between cardinal and ordinal numbers. In English we do. For example, if you are nine years old, you are in your tenth year. If an array has ten elements, the last element is the tenth element, it is nine elements away from the beginning. We could do "int array[10]; array[10th] = x;" if we wanted to mirror that. We could imagine a language that does the distinction, but I don't know what good it would do.
- SeriousM 6y agoDiscussing about 0 vs 1 indexing is like questioning the key layout of a piano. Sure, one is probably easier to learn than the other but in the end its an interface everyone is used to.