(a few days ago there was some lively discussion about relaxing type requirements for array indices which the forums seem to have lost, so this is my attempt to restart that discussion.)
it’s well known that swift is opinionated about standardizing on Int as an index type, which is why we cannot directly subscript Array with UInt, Int32, UInt8, etc. i don’t really disagree with this idea in general; i’ve always hated how C brackets all the integer types.
but there is one downside to Int, compared to say, Int32, in that Int has a huge stride: 8 bytes!
obviously, there are a lot of situations where this is not a problem at all:
-
Int uses more memory that Int32, but it’s highly uncommon for Int itself to be your memory bottleneck, so using Int fields for in-memory structures is usually okay.
-
Int can use a lot more storage than Int32 when serialized to a text-based format like JSON, but it almost never does, because JSON is a variable-length encoding:
{"_id":1}
uses the same amount of storage regardless of original bit width. so serializing Int to JSON is usually okay.
so, Int is good for in-memory stuff, and Int is good for JSON-encoded stuff.
but… Int is not good for binary-serialized stuff, like BSON, because BSON is a fixed-length encoding, and always uses 8 bytes to encode Int, which is twice as much storage as it uses to encode Int32.
i suppose one thing we can do is to use Int exclusively from the swift side, and narrow the Ints to Int32 when encoding to BSON. but now we’ve lost the compile-time guarantee of not trapping/throwing on encode, and (unlike decoders), encoders are not supposed to trap, or really, fail at all.
another approach could be to implement a more intelligent encoding + decoding strategy for these Int-typed fields, that encodes Int32 if it fits, and Int64 otherwise. but this adds a lot of complexity to the encoding + decoding logic just to serialize a simple Int field. MongoDB is totally cool with this (it brackets Int64 and Int32 when executing queries), but it’s a nightmare to handle in the strongly-typed swift world, because you have taken something that was a scalar type in your database schema, and turned it into a sum type with two cases.
i could also use a property wrapper to make the Int32 “look like an Int”, but this presents some challenges for algorithms that mutate the field, and if we really think about it, making the Int32 behave like an Int is a non-goal, the only reason we are pretending it is an Int is to be able to subscript an Array with it.
what are we to do about Int?