2017-08-23 40 views
13

tl; drGeneric Swift 4 enum z Pustki związane typ

Czy możliwe instancje rodzajowe Swift 4 Państwa enum z towarzyszącym wartości typu Void?

Tło

Używam prostego Wynik enum (podobną do antitypical Result):

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

Teraz chciałbym użyć tego wyliczenia do reprezentowania wynik operacji który nie daje rzeczywistej wartości wyniku; operacja zakończyła się niepowodzeniem lub . W tym celu zdefiniowałbym typ jako Result<Void>, ale mam problem z utworzeniem instancji wyniku, ani nie działa ona ani let res: Result<Void> = .success ani .

+0

Jesteś pewien drugiej drogi? wygląda jak działa http://swift.sandbox.bluemix.net/#/repl/599d61b1b459cc41aee76d9d – pacification

+0

Interesujące, dzięki za przykład. Ponownie sprawdziłem, ale w Xcode 9 Beta 5 otrzymuję komunikat "Brakujący argument dla parametru nr 1 w wywołaniu". –

+0

@Hamish: Prawdopodobnie masz rację (nadal byłem w SE-0110 i SE-0029 ... :) –

Odpowiedz

28

w Swift 3 można pominąć powiązanych wartość typu Void:

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

w Swift 4 trzeba przejść skojarzony wartość typu Void:

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

Czy istnieje mniej brzydkie rozwiązanie? –

+0

@RodrigoRuiz Możesz zdefiniować rozszerzenie, aby pozbyć się '(())', [zobacz moją odpowiedź] (https://stackoverflow.com/a/46863180/2976878). – Hamish

3

Pustka jest proste typealias dla pusta krotka:(), więc możesz użyć jej jako jednego z następujących:

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

W Swift 4, przypadek enum z wartością związaną z Void nie jest już równoważny przypadkowi enum z pustą listą powiązanych wartości.

Wierzę, że to jest as Martin says, wynik SE-0029, w którym nie można już przekazywać krotki argumentów do funkcji i mieć ich "splat" w parametrach (chociaż propozycja została oznaczona zaimplementowana w Swift 3, wierzę ten szczególny przypadek został podchwycony później w implementacji SE-0110 dla Swift 4).

W efekcie oznacza to nie można już nazwać (Void) -> T jako () -> T w Swift 4. Teraz trzeba przejść Void w wyraźnie:

let result = Result.success(()) 

Jednak uważam to dość brzydki, więc zazwyczaj wdrożyć przedłużenie takiego:

który pozwala mówić takie rzeczy:

var result = Result.success 
result = .success 

Warto zauważyć, że obejście to nie ogranicza się tylko do przypadków wyłudzeniowych, można go również stosować ogólnie w metodach. Na przykład:

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() 
+0

((Nice)). Nie zdawałem sobie sprawy, że możesz definiować vary na podstawie rodzaju generycznych. – GoldenJoe