Why does compactMap return a nil result?
Clash Royale CLAN TAG#URR8PPP
up vote
9
down vote
favorite
Consider this code snippet:
var a: String? = "abc"
var b: String?
let result = [a, b].compactMap $0
After executing it, result
will be
["abc"]
which is the expected result. The element of result (ElementOfResult
) here is String
.
print(type(of: result))
Array<String>
Now to the interesting part. After changing the snippet to
var a: String? = "abc"
var b: Int?
let result = [a, b].compactMap $0
and executing it, result
will be
[Optional("abc"), nil]
The element of result (ElementOfResult
) here is Any
which makes sense, because Any
is the common denominator of String
and Int
.
print(type(of: result))
Array<Any>
Why was a nil
result returned by compactMap
which contradicts its definition?
From Apple's compactMap
documentation
compactMap(_:)
Returns an array containing the non-nil results of calling the given transformation with each element of this sequence.
Declaration
func compactMap(_ transform: (Self.Element) throws -> ElementOfResult?) rethrows -> [ElementOfResult]
swift swift4.1
add a comment |Â
up vote
9
down vote
favorite
Consider this code snippet:
var a: String? = "abc"
var b: String?
let result = [a, b].compactMap $0
After executing it, result
will be
["abc"]
which is the expected result. The element of result (ElementOfResult
) here is String
.
print(type(of: result))
Array<String>
Now to the interesting part. After changing the snippet to
var a: String? = "abc"
var b: Int?
let result = [a, b].compactMap $0
and executing it, result
will be
[Optional("abc"), nil]
The element of result (ElementOfResult
) here is Any
which makes sense, because Any
is the common denominator of String
and Int
.
print(type(of: result))
Array<Any>
Why was a nil
result returned by compactMap
which contradicts its definition?
From Apple's compactMap
documentation
compactMap(_:)
Returns an array containing the non-nil results of calling the given transformation with each element of this sequence.
Declaration
func compactMap(_ transform: (Self.Element) throws -> ElementOfResult?) rethrows -> [ElementOfResult]
swift swift4.1
What is more puzzling is why the type ofresult
is[Any]
. I would have expected it to be[Any?]
– user1046037
Aug 18 at 8:50
1
@user1046037compactMap
is there to remove nil. What sense does it make to return [Any?] ifcompactMap
already made sure none of them is nil?
– Purpose
Aug 18 at 9:02
add a comment |Â
up vote
9
down vote
favorite
up vote
9
down vote
favorite
Consider this code snippet:
var a: String? = "abc"
var b: String?
let result = [a, b].compactMap $0
After executing it, result
will be
["abc"]
which is the expected result. The element of result (ElementOfResult
) here is String
.
print(type(of: result))
Array<String>
Now to the interesting part. After changing the snippet to
var a: String? = "abc"
var b: Int?
let result = [a, b].compactMap $0
and executing it, result
will be
[Optional("abc"), nil]
The element of result (ElementOfResult
) here is Any
which makes sense, because Any
is the common denominator of String
and Int
.
print(type(of: result))
Array<Any>
Why was a nil
result returned by compactMap
which contradicts its definition?
From Apple's compactMap
documentation
compactMap(_:)
Returns an array containing the non-nil results of calling the given transformation with each element of this sequence.
Declaration
func compactMap(_ transform: (Self.Element) throws -> ElementOfResult?) rethrows -> [ElementOfResult]
swift swift4.1
Consider this code snippet:
var a: String? = "abc"
var b: String?
let result = [a, b].compactMap $0
After executing it, result
will be
["abc"]
which is the expected result. The element of result (ElementOfResult
) here is String
.
print(type(of: result))
Array<String>
Now to the interesting part. After changing the snippet to
var a: String? = "abc"
var b: Int?
let result = [a, b].compactMap $0
and executing it, result
will be
[Optional("abc"), nil]
The element of result (ElementOfResult
) here is Any
which makes sense, because Any
is the common denominator of String
and Int
.
print(type(of: result))
Array<Any>
Why was a nil
result returned by compactMap
which contradicts its definition?
From Apple's compactMap
documentation
compactMap(_:)
Returns an array containing the non-nil results of calling the given transformation with each element of this sequence.
Declaration
func compactMap(_ transform: (Self.Element) throws -> ElementOfResult?) rethrows -> [ElementOfResult]
swift swift4.1
edited Aug 18 at 13:16


Peter Mortensen
12.9k1983111
12.9k1983111
asked Aug 18 at 8:10
mrvincenzo
3,34932141
3,34932141
What is more puzzling is why the type ofresult
is[Any]
. I would have expected it to be[Any?]
– user1046037
Aug 18 at 8:50
1
@user1046037compactMap
is there to remove nil. What sense does it make to return [Any?] ifcompactMap
already made sure none of them is nil?
– Purpose
Aug 18 at 9:02
add a comment |Â
What is more puzzling is why the type ofresult
is[Any]
. I would have expected it to be[Any?]
– user1046037
Aug 18 at 8:50
1
@user1046037compactMap
is there to remove nil. What sense does it make to return [Any?] ifcompactMap
already made sure none of them is nil?
– Purpose
Aug 18 at 9:02
What is more puzzling is why the type of
result
is [Any]
. I would have expected it to be [Any?]
– user1046037
Aug 18 at 8:50
What is more puzzling is why the type of
result
is [Any]
. I would have expected it to be [Any?]
– user1046037
Aug 18 at 8:50
1
1
@user1046037
compactMap
is there to remove nil. What sense does it make to return [Any?] if compactMap
already made sure none of them is nil?– Purpose
Aug 18 at 9:02
@user1046037
compactMap
is there to remove nil. What sense does it make to return [Any?] if compactMap
already made sure none of them is nil?– Purpose
Aug 18 at 9:02
add a comment |Â
2 Answers
2
active
oldest
votes
up vote
5
down vote
accepted
This is because [a, b]
is considered a [Any]
. When the element types in an array literal are entirely unrelated (Int?
and String?
), the array type is inferred to be [Any]
.
In the closure passed to compactMap
, you returned $0
, which is of type Any
. This means that $0
can never be nil
. All the optionals inside the array are all wrapped in an Any
the moment you put them in the array. Because you never return a nil
in the closure, all the elements stay in the result array.
The compiler can warn you about wrapping optionals in non-optional Any
s:
var a: String? = "abc"
let any: Any = a // warning!
But unfortunately it doesn't warn you when you create arrays.
Anyway, you can get the expected behaviour by specifying that you want a [Any?]
:
let result = ([a, b] as [Any?]).compactMap $0
So you kind of unwrap them from Any
.
Or:
let result = [a as Any?, b as Any?].compactMap $0
Why can an optional type be wrapped inside an
Any
?
According to the docs (In the Type Casting for Any
and AnyObject
section):
Any
can represent an instance of any type at all, including function types.
Thus, Optional<T>
undoubtedly can be represented by Any
.
Based on the original example, wondering how result can be of the type[Any]
and still hold anil
– user1046037
Aug 18 at 8:52
@user1046037 Because anything isAny
.Any
can hold every type.
– Sweeper
Aug 18 at 8:54
The following code throws a compilation error,let x : Any = nil
– user1046037
Aug 18 at 8:55
2
@user1046037nil
isn‘t inside the resulting array, but an optional which is nil which only printsnil
.
– Purpose
Aug 18 at 8:56
My bad, Any can be nil,var y : Int? = nil; let x : Any = y as Any
– user1046037
Aug 18 at 8:58
add a comment |Â
up vote
1
down vote
You create an Any-array and compactMap over its elements gives compactMap
only Any-elements, no Optional<Any>
which it could think about being nil or not, so all emenents stay.
add a comment |Â
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
5
down vote
accepted
This is because [a, b]
is considered a [Any]
. When the element types in an array literal are entirely unrelated (Int?
and String?
), the array type is inferred to be [Any]
.
In the closure passed to compactMap
, you returned $0
, which is of type Any
. This means that $0
can never be nil
. All the optionals inside the array are all wrapped in an Any
the moment you put them in the array. Because you never return a nil
in the closure, all the elements stay in the result array.
The compiler can warn you about wrapping optionals in non-optional Any
s:
var a: String? = "abc"
let any: Any = a // warning!
But unfortunately it doesn't warn you when you create arrays.
Anyway, you can get the expected behaviour by specifying that you want a [Any?]
:
let result = ([a, b] as [Any?]).compactMap $0
So you kind of unwrap them from Any
.
Or:
let result = [a as Any?, b as Any?].compactMap $0
Why can an optional type be wrapped inside an
Any
?
According to the docs (In the Type Casting for Any
and AnyObject
section):
Any
can represent an instance of any type at all, including function types.
Thus, Optional<T>
undoubtedly can be represented by Any
.
Based on the original example, wondering how result can be of the type[Any]
and still hold anil
– user1046037
Aug 18 at 8:52
@user1046037 Because anything isAny
.Any
can hold every type.
– Sweeper
Aug 18 at 8:54
The following code throws a compilation error,let x : Any = nil
– user1046037
Aug 18 at 8:55
2
@user1046037nil
isn‘t inside the resulting array, but an optional which is nil which only printsnil
.
– Purpose
Aug 18 at 8:56
My bad, Any can be nil,var y : Int? = nil; let x : Any = y as Any
– user1046037
Aug 18 at 8:58
add a comment |Â
up vote
5
down vote
accepted
This is because [a, b]
is considered a [Any]
. When the element types in an array literal are entirely unrelated (Int?
and String?
), the array type is inferred to be [Any]
.
In the closure passed to compactMap
, you returned $0
, which is of type Any
. This means that $0
can never be nil
. All the optionals inside the array are all wrapped in an Any
the moment you put them in the array. Because you never return a nil
in the closure, all the elements stay in the result array.
The compiler can warn you about wrapping optionals in non-optional Any
s:
var a: String? = "abc"
let any: Any = a // warning!
But unfortunately it doesn't warn you when you create arrays.
Anyway, you can get the expected behaviour by specifying that you want a [Any?]
:
let result = ([a, b] as [Any?]).compactMap $0
So you kind of unwrap them from Any
.
Or:
let result = [a as Any?, b as Any?].compactMap $0
Why can an optional type be wrapped inside an
Any
?
According to the docs (In the Type Casting for Any
and AnyObject
section):
Any
can represent an instance of any type at all, including function types.
Thus, Optional<T>
undoubtedly can be represented by Any
.
Based on the original example, wondering how result can be of the type[Any]
and still hold anil
– user1046037
Aug 18 at 8:52
@user1046037 Because anything isAny
.Any
can hold every type.
– Sweeper
Aug 18 at 8:54
The following code throws a compilation error,let x : Any = nil
– user1046037
Aug 18 at 8:55
2
@user1046037nil
isn‘t inside the resulting array, but an optional which is nil which only printsnil
.
– Purpose
Aug 18 at 8:56
My bad, Any can be nil,var y : Int? = nil; let x : Any = y as Any
– user1046037
Aug 18 at 8:58
add a comment |Â
up vote
5
down vote
accepted
up vote
5
down vote
accepted
This is because [a, b]
is considered a [Any]
. When the element types in an array literal are entirely unrelated (Int?
and String?
), the array type is inferred to be [Any]
.
In the closure passed to compactMap
, you returned $0
, which is of type Any
. This means that $0
can never be nil
. All the optionals inside the array are all wrapped in an Any
the moment you put them in the array. Because you never return a nil
in the closure, all the elements stay in the result array.
The compiler can warn you about wrapping optionals in non-optional Any
s:
var a: String? = "abc"
let any: Any = a // warning!
But unfortunately it doesn't warn you when you create arrays.
Anyway, you can get the expected behaviour by specifying that you want a [Any?]
:
let result = ([a, b] as [Any?]).compactMap $0
So you kind of unwrap them from Any
.
Or:
let result = [a as Any?, b as Any?].compactMap $0
Why can an optional type be wrapped inside an
Any
?
According to the docs (In the Type Casting for Any
and AnyObject
section):
Any
can represent an instance of any type at all, including function types.
Thus, Optional<T>
undoubtedly can be represented by Any
.
This is because [a, b]
is considered a [Any]
. When the element types in an array literal are entirely unrelated (Int?
and String?
), the array type is inferred to be [Any]
.
In the closure passed to compactMap
, you returned $0
, which is of type Any
. This means that $0
can never be nil
. All the optionals inside the array are all wrapped in an Any
the moment you put them in the array. Because you never return a nil
in the closure, all the elements stay in the result array.
The compiler can warn you about wrapping optionals in non-optional Any
s:
var a: String? = "abc"
let any: Any = a // warning!
But unfortunately it doesn't warn you when you create arrays.
Anyway, you can get the expected behaviour by specifying that you want a [Any?]
:
let result = ([a, b] as [Any?]).compactMap $0
So you kind of unwrap them from Any
.
Or:
let result = [a as Any?, b as Any?].compactMap $0
Why can an optional type be wrapped inside an
Any
?
According to the docs (In the Type Casting for Any
and AnyObject
section):
Any
can represent an instance of any type at all, including function types.
Thus, Optional<T>
undoubtedly can be represented by Any
.
edited Aug 18 at 8:59
answered Aug 18 at 8:51


Sweeper
54.5k960117
54.5k960117
Based on the original example, wondering how result can be of the type[Any]
and still hold anil
– user1046037
Aug 18 at 8:52
@user1046037 Because anything isAny
.Any
can hold every type.
– Sweeper
Aug 18 at 8:54
The following code throws a compilation error,let x : Any = nil
– user1046037
Aug 18 at 8:55
2
@user1046037nil
isn‘t inside the resulting array, but an optional which is nil which only printsnil
.
– Purpose
Aug 18 at 8:56
My bad, Any can be nil,var y : Int? = nil; let x : Any = y as Any
– user1046037
Aug 18 at 8:58
add a comment |Â
Based on the original example, wondering how result can be of the type[Any]
and still hold anil
– user1046037
Aug 18 at 8:52
@user1046037 Because anything isAny
.Any
can hold every type.
– Sweeper
Aug 18 at 8:54
The following code throws a compilation error,let x : Any = nil
– user1046037
Aug 18 at 8:55
2
@user1046037nil
isn‘t inside the resulting array, but an optional which is nil which only printsnil
.
– Purpose
Aug 18 at 8:56
My bad, Any can be nil,var y : Int? = nil; let x : Any = y as Any
– user1046037
Aug 18 at 8:58
Based on the original example, wondering how result can be of the type
[Any]
and still hold a nil
– user1046037
Aug 18 at 8:52
Based on the original example, wondering how result can be of the type
[Any]
and still hold a nil
– user1046037
Aug 18 at 8:52
@user1046037 Because anything is
Any
. Any
can hold every type.– Sweeper
Aug 18 at 8:54
@user1046037 Because anything is
Any
. Any
can hold every type.– Sweeper
Aug 18 at 8:54
The following code throws a compilation error,
let x : Any = nil
– user1046037
Aug 18 at 8:55
The following code throws a compilation error,
let x : Any = nil
– user1046037
Aug 18 at 8:55
2
2
@user1046037
nil
isn‘t inside the resulting array, but an optional which is nil which only prints nil
.– Purpose
Aug 18 at 8:56
@user1046037
nil
isn‘t inside the resulting array, but an optional which is nil which only prints nil
.– Purpose
Aug 18 at 8:56
My bad, Any can be nil,
var y : Int? = nil; let x : Any = y as Any
– user1046037
Aug 18 at 8:58
My bad, Any can be nil,
var y : Int? = nil; let x : Any = y as Any
– user1046037
Aug 18 at 8:58
add a comment |Â
up vote
1
down vote
You create an Any-array and compactMap over its elements gives compactMap
only Any-elements, no Optional<Any>
which it could think about being nil or not, so all emenents stay.
add a comment |Â
up vote
1
down vote
You create an Any-array and compactMap over its elements gives compactMap
only Any-elements, no Optional<Any>
which it could think about being nil or not, so all emenents stay.
add a comment |Â
up vote
1
down vote
up vote
1
down vote
You create an Any-array and compactMap over its elements gives compactMap
only Any-elements, no Optional<Any>
which it could think about being nil or not, so all emenents stay.
You create an Any-array and compactMap over its elements gives compactMap
only Any-elements, no Optional<Any>
which it could think about being nil or not, so all emenents stay.
answered Aug 18 at 8:18
Purpose
848414
848414
add a comment |Â
add a comment |Â
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f51906624%2fwhy-does-compactmap-return-a-nil-result%23new-answer', 'question_page');
);
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
What is more puzzling is why the type of
result
is[Any]
. I would have expected it to be[Any?]
– user1046037
Aug 18 at 8:50
1
@user1046037
compactMap
is there to remove nil. What sense does it make to return [Any?] ifcompactMap
already made sure none of them is nil?– Purpose
Aug 18 at 9:02