Big "college freshman" energy in this take:
I personally prefer to make the error state part of the objects: Streams can be in an error state, floats can be NaN and integers should be low(int) if they are invalid (low(int) is a pointless value anyway as it has no positive equivalent).
It's fine to pick sentinel values for errors in context, but describing 0x80000000 as "pointless" in general with such a weak justification doesn't inspire confidence.I have been burned by sentinel values every time. Give me sum types instead. And while I’m piling on, this example makes no sense to me:
proc fib[T: Fibable](a: T): T =
if a <= 2:
result = 1
else:
result = fib(a-1) + fib(a-2)
Integer is the only possible type for T in this implementation, so what was the point of defining Fibable?
Without the low int the even/odd theorem falls apart for wrap around I've definitely seen algorithms that rely upon that.
I would agree, whether error values are in or out of band is pretty context dependent such as whether you answered a homework question wrong, or your dog ate it. One is not a condition that can be graded.