Why Array.Index is 'Int' but not 'UInt'?

So, why we have this initializer for an Array
let a = Array(repeating: _, count: Int) and not let a = Array(repeating: _, count: UInt64)
Index in an array can not be negative. And iOS 9 does not allow me to make well capacity array for storing all seconds since 1970 year.

From Swift guide:

Use UInt only when you specifically need an unsigned integer type with the same size as the platform’s native word size. If this isn’t the case, Int is preferred, even when the values to be stored are known to be nonnegative. A consistent use of Int for integer values aids code interoperability, avoids the need to convert between different number types, and matches integer type inference, as described in Type Safety and Type Inference.

3 Likes

There are two ways of manipulating indices:

  1. using index apis, like firstIndex, or index(after:)
    If you use them, you don't care if index is signed or unsigned, because you don't ever touch it as a number
  2. using arithmetics, like arr[3-foo+bar]
    if you manipulating indices like that you have to be careful anyway, because -1 is as wrong as size+1 or even 3 when you meant 2.
    If you manipulate indices with arithmetics though, Int has an advantage over UInt because you don't have to convert your numbers back and forth between signed and unsigned, and you can temporarily go into negatives when computing the final index
1 Like

I understand about interoperability, but next simple and useful code does not work on iOS9

let searchIndex = Int(Date().timeIntervalSince1970 * 10)
let z = [1, 2, 3][searchIndex]

Because of overflowing Int value

You're accessing element beyond the 4294967296th. You need at least 16GB to store that many data on 32-bit machine, doubling that for 64-bit. That's a lot of space. I think you'd be better off rolling your own storage.

Also, since Date().timeIntervalSince1970 * 10 ~ 15840M, you'd need at least 59GB on 32-bit machine.

2 Likes

It is not actually storage, the [1, 2, 3] may be GenericStruct which works with Array.Index type. I mean iOS9 is off-board already for modern code.

What're you trying to do? Collection.Index is only appropriate to use with that Collection. If you have your own GenericStruct, then you should decide your own appropriate Index.

Also your original question is about Array(repeating: _, count: Int) which creates Array, not GenericStruct.

I have a collection with 300 capacity. And I'm trying to get all seconds from 1970 and divide it to my capacity and get a reminder for getting an index of an element. A generics example from my previous post is not quite good for now.

Ok, from the look of it, you’re trying to cram all those entries into an array of 300 elements.

There are 2 ways you can do it.

  1. Wrap the array in your custom implementation of TimestampEntries, which of course, would have UInt64 as an Index, or
  2. Use UInt64 in your computation, and convert them to Int when accessing array.

It seems you’re trying to do 2. the reason it doesn’t work is that, you have an array of 300 elements. It doesn’t care if you’re accessing data of April 2015, all it cares is where in that 300 buckets do you want. So you need to convert 15840000000 (for today’s value) to a number between 0..<300.

Though I think what you really want is a Dictionary, which is also available in Swift.

I realize that this is not the main point of the question but:

The number of seconds since 1970 is:

1_584_000_000

which is less than UInt32.max:

4_294_967_295


Yes, you need 16 GB to store 232 elements (assuming each element has a stride of four bytes, and using binary measurement, GiB).

No, not just doubling, you'd need to double 32 times (once for each added bit), so
you'd need 68 719 476 736 GiB = 67 108 864 TiB = 64 EiB (exabytes) to store 264 elements (assuming the same element type).

:nerd_face:

EDIT:
But perhaps you meant "if you'd want to store the same number of elements, but elements being 8-byte UInt64 instead of 4-byte UInt32"? In that case you'd clearly need to double it.

He actually *10 at the end, but yea.

Don’t for get that Int is 64-bit that, so double that :stuck_out_tongue_winking_eye:. Which should be 128 EiB (exbibyte). :nerd_face:

That's why I wrote:

: )

Oh, I missed that.

1 Like