6 ms·
I'm curious what the motivation was to use int instead of uint considering indexes cannot be negative in Go.
by kbirkeland 8y ago
I'm curious what the motivation was to use int instead of uint considering indexes cannot be negative in Go.
- pxia 8y agoBecause you want to represent errors. For example a find() function that returns the index of some element: you want to return -1 when the element doesn't exist.
- growse 8y agoShouldn't idiomatic go return an error instead? Magic number ranges for errors always seemed a bit old-fashioned.
- pxia 8y agoIt's just an example... Another example would be you want to iterate your array in reverse. The normal `for (uint i=size-1; i >= 0; i--)` won't work.
- growse 8y agoThat example doesn't work precisely because you're conflating the concept of the loop counter (which type represents an integer that needs to be able to go <0) with the array index accessor. There's no reason for these two things to be the same type, it's just a pattern that accidentally works because we allow arrays to be accessed using a type that represents negative numbers. What would be a more compelling argument is to use int in the same way that python does - a negative accessor means offset from the end of the array, not the start. I'm not sure golang lets you do this though...?
- xyproto 8y agoReturning -1 instead of an error is abusing the type system. In C, there is no error type, so it might be excusable there, but it is inexcusable in Go, IMO.
- nordsieck 8y ago> I'm curious what the motivation was to use int instead of uint considering indexes cannot be negative in Go. I want to emphasize that I do not know the true answer to this question. I think that indexes are int to play nicely with a decrementing loop counter. Doing: for i := len(n) - 1; i >= 0; i-- { fmt.Println(n[i]) } requires i to be signed due to the last iteration.
- a1369209993 8y agoI'm not sure about go, but in C this could be: for(size_t i = zn; i-- > 0 ;) printf("%s\n",n[i]); (This is a large part of why unsigned over/underflow is well-defined behavior in C.)
- nordsieck 8y agoIn Go, i++/i-- is a statement, not an expression, so that doesn't work. More generally, assignment is always a statement, and never an expression (e.g. you can't say a = b = c)
- jerf 8y agoDespite most of my professional programming being in Go nowadays, I am extremely sympathetic to the Haskell/FP way of thinking about things, and trying to make invalid state unrepresentable. However, having made the mistake a few times now of trying to use "unsigned ints" for things that I want to assert are never negative, I've learned the hard way not to do that. The problem is, there's always some bug you have in the program that will drive the uint "negative", wrapping over to a huge number. Unfortunately, since you get no warning when that happens, it tends to take longer to show up, and without a clear cutoff to say "ah, this is clearly invalid" it can be hard to even program detection code, whereas checking for "less than 0" can be unambiguous. I'd loooove it if I could easily, cheaply, and universally (i.e., not just in Go, but across all my programming languages) turn on a behavior that says "if this int or uint under or overflows, throw an exception instead of trying to do whatever stupid thing you're going to do". I get the sense this is heading down the road where in 20 or 30 years, this is just going to be common sense. However, we are very early on the road yet from what I can see. Whenever I bring it up, even today, even in this sort of context, it still is generally negatively received. (But not uniformly. A few other people agree. I think momentum is with me. I'm not sure my programming career will live long enough to see it, though.)
- greenleafjacob 8y ago> if this int or uint under or overflows, throw an exception Overflow flags are supported on some architectures, so it would really just be a matter of checking that flag.
- 4ad 8y agoExcept in Go, types are defined using modular 2s complement. Overflow is not considered a problem, it's a feature that code depends on.
- LukeShu 8y agoThe spec says: > For signed integers, the operations +, -, , /, and << may legally overflow and the resulting value exists and is deterministically defined by …* It does not go on to define the overflow values; that gets to be implementation defined. This is in contrast to unsigned integers, which the spec does precisely define overflow for.
- IshKebab 8y agoIn general it is nicer to use signed numbers for indices. The actual index can't be negative, true, but differences between them can, and it means you don't have so many dubious sign conversions.
- joppy 8y agoUsing unsigned indexes would be fine if the program automatically throws an error on wrapping. Otherwise, it’s an accident waiting to happen, since you have to code all of your arithmetic keeping in mind the fact that the numbers are trying to blow up in your face. If x is unsigned, then you can’t rearrange an inequality like x >= 4 into x - 4 >= 0, since the first inequality is only true sometimes, whereas the second is true always. This looks obvious, but bury it a little way into some nontrivial index arithmetic and boom. Another more aesthetic reason is that indices can represent offsets into a structure relative to some other index, and in this case you really need negative numbers.