Search code examples
swiftstaticsetmapping

Static method wrapper for map in Swift


Every method in Swift has correspondent static function generated by Swift automatically.
But I'm having hard times to apply this concept for map.
For example. This is a canonical way of doing things:

let numbers = Set([1, 2, 3])
let doubled = numbers.map { $0 * 2 }
print(doubled) // [2, 4, 6]

What I want is to make the following code compile and work (because in theory it should compile and work just like the code above):

let numbers = Set([1, 2, 3])
let doubled = Set.map(numbers) { $0 * 2 }
print(doubled) // [2, 4, 6]

P.S. By the way, how is this feature called officially?


Solution

  • Assuming you mean the fact that an instance method like this:

    class C {
        func foo(x: T1, y: T2) -> R { ... }
    }
    

    can also be called as if it were a static method like this:

    class C {
        static func foo(`self`: C) -> (T1, T2) -> R { ... }
    }
    

    This is called currying, but only on the first parameter. Usually currying foo (above) would mean func foo() -> (C) -> (T1) -> (T2) -> R. See also: https://stackoverflow.com/a/25375190/5133585

    You can use the static version of map like this:

    let numbers = Set([1, 2, 3])
    let doubled = try Set.map(numbers)() { $0 * 2 }
    print(doubled)
    

    Note that the extra () after map(numbers). Without it, the parser would think that the closure is an argument for the Set.map call. The () is needed to make it clear that the closure is an argument for the function returned by map. You can also not use the trailing closure syntax:

    try Set.map(numbers)({ $0 * 2 })
    

    You also need try, because map is declared with rethrows:

    func map<T>(_ transform: (Self.Element) throws -> T) rethrows -> [T]
    

    Normally, rethrows means that if transform doesn't throw, map also doesn't throw. But since the static version of map only takes a Set and returns a ((Self.Element) throws -> T) -> [T], it cannot know whether the closure you are going to pass throws or not. Therefore, it stays on the safe side and assume it will throw.