Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

map(keyPath) where keyPath is a variable

let arr = [(1, 1), (2, 2), (3, 3), (4, 4), (5, 5)]
arr.map(\.0) // [1, 2, 3, 4, 5]

Works great. But the below code doesn't compile:

let keyPath = \(Int, Int).0
arr.map(keyPath)

Cannot convert value of type 'WritableKeyPath<(Int, Int), Int>' to expected argument type '((Int, Int)) throws -> T'.
Generic parameter 'T' could not be inferred.

like image 930
Roman Avatar asked Sep 07 '26 22:09

Roman


1 Answers

Array.map expects a closure with signature (Element) throws -> T.

In Swift 5.2, key paths were allowed to be passed in as functions/closures (here's an evolution proposal), but only as literals (at least, according to the proposal, it says "for now", so perhaps this restriction would be lifted).

To overcome this, you can create an extension on Sequence that accepts a key path:

extension Sequence {
   func map<T>(_ keyPath: KeyPath<Element, T>) -> [T] {
      return map { $0[keyPath: keyPath] }
   }
}

(credit to: https://www.swiftbysundell.com/articles/the-power-of-key-paths-in-swift/)

Then you can do what you wanted:

let keyPath = \(Int, Int).0
arr.map(keyPath)
like image 143
New Dev Avatar answered Sep 11 '26 10:09

New Dev



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!