I simplified my code as much as I could to make it still be a reproducible example. When I use contains
like this in a chain of calls it does compile, work and contains
accepts nil
when it shouldn't, I think.
let array = [1, 2, 3, 4, 5].filter { _ in
[1, 2, 3].map { smallNumber in
"\(smallNumber)"
}
.contains(nil)
}
But when I assign map
result to a variable and then call contains
with nil
value the code doesn't even compile.
let array = [1, 2, 3, 4, 5].filter { _ in
let mappedNumbers = [1, 2, 3].map { smallNumber in
"\(smallNumber)"
}
return mappedNumbers.contains(nil)
}
Xcode is complaining about 'nil' is not compatible with expected argument type 'String'
, that is right.
I expect the same error in the first example.
The compiler can automatically wrap a value into an optional, if required by the context. That is what makes simple assignments like
let value: Int? = 123
possible. In your first example, the return type of the closure is inferred as String?
from the context, so that the map
returns [String?]
, and .contains(nil)
can be applied to it. Ie the compiler understands the code as
let array = [1, 2, 3, 4, 5].filter { _ in
[1, 2, 3].map { smallNumber -> String? in
"\(smallNumber)"
}
.contains(nil)
}
In the second example the compiler does not have that context, and mappedNumbers
has the type [String]
. You can make it compile by specifying the closure return type String?
explicitly:
let array = [1, 2, 3, 4, 5].filter { _ in
let mappedNumbers = [1, 2, 3].map { smallNumber -> String? in
"\(smallNumber)"
}
return mappedNumbers.contains(nil)
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.