Why does compactMap return a nil result?

The name of the pictureThe name of the pictureThe name of the pictureClash 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]








share|improve this question






















  • 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?] if compactMap already made sure none of them is nil?
    – Purpose
    Aug 18 at 9:02














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]








share|improve this question






















  • 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?] if compactMap already made sure none of them is nil?
    – Purpose
    Aug 18 at 9:02












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]








share|improve this question














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]










share|improve this question













share|improve this question




share|improve this question








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 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?] if compactMap 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






  • 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















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












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 Anys:



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.






share|improve this answer






















  • 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










  • The following code throws a compilation error, let x : Any = nil
    – user1046037
    Aug 18 at 8:55






  • 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










  • My bad, Any can be nil, var y : Int? = nil; let x : Any = y as Any
    – user1046037
    Aug 18 at 8:58


















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.






share|improve this answer




















    Your Answer





    StackExchange.ifUsing("editor", function ()
    StackExchange.using("externalEditor", function ()
    StackExchange.using("snippets", function ()
    StackExchange.snippets.init();
    );
    );
    , "code-snippets");

    StackExchange.ready(function()
    var channelOptions =
    tags: "".split(" "),
    id: "1"
    ;
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function()
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled)
    StackExchange.using("snippets", function()
    createEditor();
    );

    else
    createEditor();

    );

    function createEditor()
    StackExchange.prepareEditor(
    heartbeatType: 'answer',
    convertImagesToLinks: true,
    noModals: false,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: 10,
    bindNavPrevention: true,
    postfix: "",
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    );



    );













     

    draft saved


    draft discarded


















    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






























    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 Anys:



    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.






    share|improve this answer






















    • 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










    • The following code throws a compilation error, let x : Any = nil
      – user1046037
      Aug 18 at 8:55






    • 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










    • My bad, Any can be nil, var y : Int? = nil; let x : Any = y as Any
      – user1046037
      Aug 18 at 8:58















    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 Anys:



    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.






    share|improve this answer






















    • 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










    • The following code throws a compilation error, let x : Any = nil
      – user1046037
      Aug 18 at 8:55






    • 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










    • My bad, Any can be nil, var y : Int? = nil; let x : Any = y as Any
      – user1046037
      Aug 18 at 8:58













    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 Anys:



    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.






    share|improve this answer














    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 Anys:



    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.







    share|improve this answer














    share|improve this answer



    share|improve this answer








    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 a nil
      – user1046037
      Aug 18 at 8:52











    • @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






    • 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










    • 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











    • @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






    • 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










    • 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













    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.






    share|improve this answer
























      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.






      share|improve this answer






















        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.






        share|improve this answer












        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.







        share|improve this answer












        share|improve this answer



        share|improve this answer










        answered Aug 18 at 8:18









        Purpose

        848414




        848414



























             

            draft saved


            draft discarded















































             


            draft saved


            draft discarded














            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













































































            Comments

            Popular posts from this blog

            List of Gilmore Girls characters

            What does second last employer means? [closed]

            One-line joke