I think that the rationale for using int for array indices and lengths and so on is to avoid shooting yourself in the foot with wrap-around arithmetic (again, my thesis being that when 99% of people use integers, they expect them to behave like integers and not wrap)
Take for example code which finds consecutive differences in a list, something like
for i := 0; i < len(list) - 1; i++ {
print(list[i+1] - list[i])
}
This code looks fine and reasonable, and we even avoided the off-by-one error at the end. However, if len(list) is a uint and we run this on an empty list, len(list) - 1 is then 2^32 or something, and the program explodes.
So this is the rationale for using signed integers rather than unsigned integers. I think the language semantics should go further, and use true integers pretty much everywhere. Note that the compiler could still easily see that the index variable in the loop above is bounded, and use a machine word under-the-hood. But the programmer only ever has to think about well-behaved integers.
Take for example code which finds consecutive differences in a list, something like
This code looks fine and reasonable, and we even avoided the off-by-one error at the end. However, if len(list) is a uint and we run this on an empty list, len(list) - 1 is then 2^32 or something, and the program explodes.So this is the rationale for using signed integers rather than unsigned integers. I think the language semantics should go further, and use true integers pretty much everywhere. Note that the compiler could still easily see that the index variable in the loop above is bounded, and use a machine word under-the-hood. But the programmer only ever has to think about well-behaved integers.