swiftswift5swift-keypath

Apply KeyPath in map() in simplest form


let test = [4, 5, 3, 1, 3]
print(
    test.map { $0 }
)
print(
    test.map(\.self)  // Doesn't compile  
)

Error:

Type of expression is ambiguous without more context

Why doesn't it work? Seems like it should.
If isn't this way, how else can we rid of the ugly { $0 } here?

Maybe an example with compactMap will make more cense))

let test = [4, 5, nil, 3, 1, nil, 3]
print(
    test.compactMap { $0 }
)
print(
    test.compactMap(\.self)  // Doesn't compile  
)

Error:

Cannot convert value of type 'WritableKeyPath<_, _>' to expected argument type '(Int?) throws -> ElementOfResult?'


Solution

  • Why doesn't it work? Seems like it should.

    You are right. Both of your examples should compile because

    In fact the latter proposal explicitly mentions an example similar to yours. However, that does not compile (as of Xcode 11.7 and Xcode 12 beta):

    [1, nil, 3, nil, 5].compactMap(\.self)
    // error: generic parameter 'ElementOfResult' could not be inferred
    

    That is a bug. It has already been reported as

    The bug report mentions a custom extension as a possible workaround:

    extension Optional { var mySelf: Self { self } }
    
    [1, nil, 3, nil, 5].compactMap(\.mySelf)