genéricos como parâmetros para um fechamento em swift

Estou tendo problemas para escrever a seguinte function como um encerramento

func myfunc(param: S) { ... } 

eu tentei

 let myClosure = {(param: S) in ... } 

mas isso não funciona.

Alguma sugestão?

Eu acredito que o que você está pedindo não faz sentido (não tem nada a ver com Swift). Embora eu esteja interessado em provar que estou errado, não acredito que isso possa ser razoavelmente criado em qualquer linguagem fortemente tipada. (EDIT: continuando minha pesquisa, acredito que isso seria possível em uma linguagem com polymorphism de primeira class, mas não tenho conhecimento de nenhuma linguagem de uso geral que realmente tenha esse recurso.)

 let myClosure = {(param: S) in ... } 

Qual tipo você esperaria que o myClosure fosse? Um genérico cria um tipo abstrato. Não se torna um tipo real até que seja especializado. Então myClosure seria de um tipo abstrato em si. É como pedir uma instância de uma aula abstrata. O ponto inteiro de “abstrato” é que você não pode construir um. O melhor que você poderia dizer seria que o myClosure seria, ele próprio, um tipo que você precisaria instanciar em uma instância real (mas, em seguida, não faça nenhum sentido; você não let tipos).

Quando você coloca isso em uma struct , o que você realmente está fazendo é criar um tipo abstrato em que você se especializará em um tipo real quando criar uma instância.

Agora o que faria sentido IMO (mas parece atualmente ser impossível), é isso:

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

Isso faz sentido porque você está definindo um tipo abstrato ( Mapping ), mas instanciando um tipo concreto Mapping . Infelizmente, typealias não parece apoiar os genéricos neste momento, portanto, uma struct é provavelmente a melhor ferramenta que temos.


Note que enquanto typealias é um busto, é claramente possível especializar variables ​​de function. Isso não é um fechamento, eu sei, mas pode ser útil em algumas das mesmas situações.

 func Identity(i:T) -> T { return i } let identityInt:(Int -> Int) = Identity identityInt(1) // => 1 

Usando isso para explorar um pouco mais o problema dos tipos abstratos, considere:

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

Isso não consegue compilar com o erro:

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

Isso é porque o tipo (T) -> T não é um tipo concreto, então você não pode ter um chamado x . Compare isso com identityInt , que eu explicitamente me especializei em um tipo concreto, e então poderia construir.

Você poderia tentar quebrar seu encerramento dentro de uma estrutura que declara o tipo genérico. Algo como:

 struct ClosureWrapper { let myClosure = {(param: S) in ... } } 

É claro que, neste ponto, seu encerramento também pode ser uma function normal: