Первоклассная универсальная функция в Swift?

Swift имеет функции первого класса, которые могут быть переданы в качестве аргументов.

func a() {
}

func b(x: ()) {
}

// Pass a to b…
b(a)

Swift имеет общие функции.

func generic<T>(x: T) {
}

Но позволяет ли Swift передать обобщенную функцию в качестве аргумента другой функции?

let anIntService = Service<Int>()
let astringService = Service<String>()

func attach<T>(service: Service<T>, to value: T) {
  // Perform type safe attaching of `value` to `service`.
}

func doAttaching(attach: (Service<T>, to T)->Void) {
  attach(anIntService, to: 42)
  attach(aStringService, to: "Hello World!")
}

doAttaching(attach)

... Или это только позволяет мне передать конкретную реализацию обобщенной функции?

Если это возможно, пожалуйста, проиллюстрируйте синтаксис для определения функции, которая принимает обобщенную функцию в качестве аргумента.

Если это не поддерживается, обходной путь состоит в том, чтобы определить универсальную функцию как метод структуры или чего-то еще и передать вместо этого. Это не идеально, так как функция-потребитель не имеет такого приятного синтаксиса вызова, что они должны сделать:

func doAttaching(attach: Attacher) {
  attacher.attach(anIntService, to: 42)
  attacher.attach(aStringService, to: "Hello World")
}

3 ответа

Эта функция обычно называется типами с высоким родством (HKT) и в настоящее время не поддерживается в Swift.

Это, однако, обсуждалось в списке рассылки swift-evolution.

Да, вот пример:

func identity<T>(param: T) -> T {
    return param
}

func callFunction<U>(function: U->U, paramater: U) -> U {
    return function(paramater)
}

let param = 123

let result = callFunction(identity, paramater: param);

print(result)

(Вы можете запустить его здесь)

Я понял, что через пять лет после того, как задал этот вопрос, Swift поддерживает что-то вроде этого, что может быть полезно черезcallAsFunction.

Вот пример:

      
final class Service<T> {
    // Implementation here
}

final class Attacher {
    // Important state here.
    var state = Void()
    
    func callAsFunction<T>(service: Service<T>, to: T) {
        // Implementation here.
    }
}

func doAttaching(attach: Attacher) {
    attach(service: Service<Int>(), to: 42)
    attach(service: Service<String>(), to: "Hello World!")
}

А Repeaterмогут быть переданы в общий код и обеспечивают полезное поведение.

Другие вопросы по тегам