1

I used Any type to store array of multiple optional type with default value, and got unexpected result.

let i64: Int64? = nil

print([
    i64 ?? 0,
    i64 ?? 0,
    i64 ?? 0
])

Then, [Optional(0), 0, 0] is printed.

Following is my detailed experiment. First, I declared the following variables:

let i64: Int64? = nil
let i32: Int32? = nil
let i: Int? = nil
let str: String? = nil

Then I put some of these variables into an Array and assigned to Any type.

var any: Any

any = [
    i64 ?? 0,
    i64 ?? 0,
    i64 ?? 0
]
print(any)                    // [0, Optional(0), 0]
print(type(of: any))          // Array<Any>

It's weird that one of the value is Optional(0) and others retained 0. And the position of that optional variable are not always located at the same index, it's placed randomly.

This situation occurred only if size of array is 3 or greater, array with 2 elements worked as expected.

any = [
    i64 ?? 0,
    i64 ?? 0
]
print(any)                    // [0, 0]
print(type(of: any))          // Array<Int64>

any = [
    i64 ?? 0,
    str ?? ""
]
print(any)                    // [0, ""]
print(type(of: any))          // Array<Any>

And I found that if I specified the type of those default value, it seems worked perfectly.

any = [
    i64 ?? Int64(0),
    i64 ?? Int64(0),
    i64 ?? Int64(0)
]
print(any)                    // [0, 0, 0]
print(type(of: any))          // Array<Int64>

any = [
    i64 ?? Int64(0),
    i64 ?? Int64(0),
    i64 ?? Int64(0),
    str ?? ""
]
print(any)                    // [0, 0, 0, ""]
print(type(of: any))          // Array<Any>

However, I couldn't conclude with a good explanation why this can work.

In my opinion, i64 ?? 0 should always considered 0 as same type of i64, which is Int64. It comes from the following assignment test:

let test1 = i64 ?? 0
print(type(of: test1))        // Int64
let test2 = i64 ?? Int64(0)
print(type(of: test2))        // Int64
let test3 = i64 ?? Int32(0)   // compiled error

But why i64 ?? 0 value in Array act different to i64 ?? Int64(0)?

Should I really need to specify the type of 0 in every assign operation? Is any way to make the array works as expected without the Int64(0) type conversion.

Allen Yang
  • 11
  • 2
  • I am not able to reproduce your issue. What version of Xcode are you using and what is your macOS version? – vacawama May 29 '21 at 19:14
  • Not an answer, but even if you're going to ultimately assign your array to an variable of type `Any`, you should still use `as [Int64]` to both speed up compilation, and to make the type information more clear in this context, which can clearly be a little ambiguous at times. – Alexander May 29 '21 at 21:07
  • @Alexander Thanks for your reminder! Actually, I'm making a JSON-like data structure but not only a simple array. In other words, I have this problem when I tried to use `Dictionary` type, and the value field of dictionary (`Any` type) could be Boolean, Int, Array or another Dictionary. I simplify the problem to a single Array and make it reproducible so you guys can check this easier. Any suggestions to my implementation of JSON-like Dictionary are also welcome. – Allen Yang May 30 '21 at 03:32
  • @vacawama I'm using Xcode 12.5 (12E262) on macOS 11.3 (20E232). Thanks for your advice, I didn't think it might be a compiler problem. I tried it on some online Swift playground and it seems work well. Maybe it's a Swift compiler issue, can I have your Xcode version? – Allen Yang May 30 '21 at 03:36

0 Answers0