Подтвердить что ты не робот

Generics как параметры для закрытия в быстрых

У меня возникла проблема с записью следующей функции в виде замыкания

func myfunc<S where S: MyProtocol, S: MySuperClass>(param: S) { ... }

Я пробовал

let myClosure = {<S where S: MyProtocol, S: MySuperClass>(param: S) in ... }

но это не сработает.

Любые предложения?

4b9b3361

Ответ 1

Я считаю, что то, о чем вы просите, не имеет смысла (не имеет никакого отношения к Swift). Хотя я заинтересован в том, чтобы оказаться ошибочным, я не считаю, что это можно было бы разумно создать на любом строго типизированном языке. (EDIT: продолжая мои исследования, я считаю, что это возможно на языке с первоклассным полиморфизмом, но я не знаю каких-либо общедоступных языков, которые действительно имеют эту функцию.)

let myClosure = {<S where S: MyProtocol, S: MySuperClass>(param: S) in ... }

Какой тип вы ожидали бы myClosure? Общий тип создает абстрактный тип. Он не становится настоящим типом, пока он не станет специализированным. Итак, myClosure будет иметь абстрактный тип. Это как просить экземпляр абстрактного класса. Весь смысл "абстрактного" заключается в том, что вы не можете его построить. Лучшее, что вы могли бы сказать, было бы в том, что myClosure сам будет типом, который вам нужно создать в реальном экземпляре (но тогда let не имеет никакого смысла, вы не let).

Когда вы обертываете это в struct, то, что вы действительно делаете, это создание абстрактного типа, который вы будете специализировать в реальном типе при создании экземпляра.

Теперь, что будет иметь смысл ИМО (но в настоящее время это невозможно), вот что:

typealias Mapping<S> = S -> S
let identity: Mapping<Int> = { return $0 }

Это имеет смысл, потому что вы определяете абстрактный тип (Mapping), но затем создаете конкретный тип Mapping<Int>. К сожалению, typealias не поддерживает поддержку дженериков в этой точке, поэтому struct, вероятно, лучший инструмент, который у нас есть.


Обратите внимание, что в то время как typealias является бюстом, очевидно, что можно специализировать сами переменные функции. Это не закрытие, я знаю, но может быть полезно в некоторых ситуациях.

func Identity<T>(i:T) -> T {
  return i
}

let identityInt:(Int -> Int) = Identity
identityInt(1) // => 1

Используя это, чтобы изучить проблему абстрактных типов немного больше, рассмотрим:

func Identity<T>(i:T) -> T { return i }
let x = Identity

Это не скомпилируется с ошибкой:

error: cannot convert the expression type '(T) -> T' to type '(T) -> T'

Это потому, что тип (T) -> T не является конкретным типом, поэтому вы не можете называть его x. Сравните это с identityInt, который я явно специализировал в конкретном типе, а затем мог построить.

Ответ 2

Вы можете попробовать обернуть свое закрытие внутри структуры, объявляющей общий тип. Что-то вроде:

struct ClosureWrapper<S where S: MyClass, S: MyProtocol> {
    let myClosure = {(param: S) in ... }
}

Конечно, на этом этапе ваше закрытие также может быть нормальной функцией: P