50 votes

Enum générique Swift 4 avec type associé Void

en résumé

Est-il possible d'instancier un membre générique d'enum Swift 4 avec une valeur associée de type Void ?

Contexte

J'utilise un simple Résultat enum (similaire à Résultat antitypique ) :

enum Result<T> {
  case success(T)
  case error(Error?)
}

Maintenant, j'aimerais utiliser cet enum pour représenter le résultat d'une opération qui ne produit pas de valeur de résultat réelle ; l'opération est soit a réussi ou échoué . Pour cela, je définirais le type comme Result<Void> mais je ne parviens pas à créer l'instance de résultat, ni l'un ni l'autre. let res: Result<Void> = .success ni let res: Result<Void> = .success() travaux.

0 votes

Vous êtes sûr de la deuxième méthode ? Il semble qu'elle fonctionne. swift.sandbox.bluemix.net/#/repl/599d61b1b459cc41aee76d9d

0 votes

Intéressant, merci pour l'exemple. J'ai revérifié, mais dans Xcode 9 Beta 5 j'obtiens Missing argument for parameter #1 in call .

0 votes

@Hamish : Vous avez probablement raison (j'étais encore à SE-0110 et SE-0029 ... :)

82voto

Martin R Points 105727

En Swift 3, vous pouvez omettre la valeur associée de type Void :

let res: Result<Void> = .success()

En Swift 4, vous devez passer une valeur associée de type Void :

let res: Result<Void> = .success(())
// Or just:
let res = Result.success(())

15 votes

Existe-t-il une solution moins laide ?

1 votes

@RodrigoRuiz Vous pouvez définir une extension pour vous débarrasser des (()) , voir ma réponse .

54voto

Hamish Points 42073

Dans Swift 4, un cas d'enum avec un élément de type Void n'est plus équivalent à un cas d'énumération avec une liste vide de valeurs associées.

Je crois que c'est ça, comme le dit Martin à la suite de SE-0029 où il n'est plus possible de passer un n-uplet d'arguments à une fonction et de les faire "éclater" parmi les paramètres (bien que cette proposition ait été marquée dans Swift 3, je crois que ce cas particulier a été repris plus tard dans l'implémentation de la fonction SE-0110 pour Swift 4).

En conséquence, cela signifie que vous ne pouvez plus appeler une (Void) -> T en tant que () -> T dans Swift 4. Vous devez maintenant passer Void de manière explicite :

let result = Result.success(())

Cependant, je trouve cela assez laid, donc j'implémente généralement une extension comme celle-ci :

extension Result where Success == Void {
    static var success: Result {
        return .success(())
    }
}

Ce qui vous permet de dire des choses comme ça :

var result = Result.success
result = .success

Il convient de noter que cette solution de contournement n'est pas seulement limitée aux cas d'enum, elle peut également être utilisée avec les méthodes en général. Par exemple :

struct Foo<T> {
  func bar(_ a: T) {}
}

extension Foo where T == Void {
  func bar() { bar(()) }
}

let f = Foo<Void>()

// without extension:
f.bar(())

// with extension:
f.bar()

3 votes

((Nice)). Je n'avais pas réalisé que l'on pouvait définir des variables basées sur le type de générique.

0 votes

Une solution géniale ! Je suis passé de .success(Void()) à ceci

0 votes

La version de Swift 5 serait extension Result where Success == Void { ... } mais pour une raison quelconque, let r1 = Result<Void, Error>.success ne compile pas avec "Ambiguous use of 'success'", mais let r2: Result<Void, Error> = .success compile sans problème.

5voto

KaQu Points 71

Void est un simple typealias pour le tuple vide : () donc vous pouvez l'utiliser comme l'un des suivants :

let res1: Result<Void> = .success(())
let res2 = Result<Void>.success(())
let res3 = Result.success(() as Void)
let res4 = Result.success(())

4voto

WongWray Points 507

Swift 5 a mis à jour Resultat pour exiger le paramètre Failure, mais exige toujours la valeur associée :

let res: Result<Void, Error> = .success(())

4voto

Saqib Saud Points 1536

I trouver .success(Void()) est plus descriptif et plus simple.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X