2017-08-23 43 views
13

tl; drGeneric Swift 4 enum với Void liên quan đến loại

Có thể để nhanh chóng một generic Swift 4 thành viên enum với một giá trị liên quan đến các loại Void?

nền

Tôi đang sử dụng một đơn giản quả enum (tương tự như antitypical Result):

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

Bây giờ tôi muốn sử dụng enum này để biểu diễn kết quả của một hoạt động không mang lại giá trị kết quả thực tế; hoạt động là đã thành công hoặc không thành công. Đối với điều này tôi muốn xác định loại là Result<Void>, nhưng tôi đang đấu tranh với cách tạo ra cá thể kết quả, không phải let res: Result<Void> = .success cũng không let res: Result<Void> = .success() hoạt động.

+0

bạn có chắc chắn về cách thứ hai không? có vẻ như nó hoạt động http://swift.sandbox.bluemix.net/#/repl/599d61b1b459cc41aee76d9d – pacification

+0

Thú vị, cảm ơn ví dụ. Tôi đã kiểm tra lại, nhưng bên trong Xcode 9 Beta 5 tôi nhận được 'Thiếu đối số cho tham số # 1 trong cuộc gọi'. –

+0

@ Hamish: Có lẽ bạn đã đúng (tôi vẫn ở SE-0110 và SE-0029 ... :) –

Trả lời

28

Trong Swift 3 bạn có thể bỏ qua các giá trị liên quan đến các loại Void:

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

Trong Swift 4 bạn phải vượt qua một giá trị liên quan đến các loại Void:

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

Có một giải pháp ít xấu xí hơn không? –

+0

@RodrigoRuiz Bạn có thể định nghĩa một phần mở rộng để loại bỏ '(())', [xem câu trả lời của tôi] (https://stackoverflow.com/a/46863180/2976878). – Hamish

3

Void là typealias đơn giản cho trống tuple:() để bạn có thể sử dụng nó như bất kỳ sau đây:

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

Trong Swift 4, một trường hợp enum với giá trị được liên kết là Void không còn tương đương với một trường hợp enum với danh sách trống của các giá trị được liên kết.

Tôi tin rằng đây là, as Martin says, kết quả của SE-0029 nơi bạn không còn có thể truyền một bộ đối số cho hàm và có "splat" trên các tham số (mặc dù đề xuất đã được đánh dấu được thực hiện trong Swift 3) trường hợp cụ thể này được chọn sau này trong việc thực hiện SE-0110 cho Swift 4).

Kết quả là, điều này có nghĩa là bạn không còn có thể gọi một (Void) -> T như một () -> T trong Swift 4. Bây giờ bạn phải vượt qua Void trong một cách rõ ràng:

let result = Result.success(()) 

Tuy nhiên, tôi tìm thấy điều này khá xấu xí, vì vậy tôi thường thực hiện một phần mở rộng như thế này:

Cho phép bạn nói những điều như thế này:

var result = Result.success 
result = .success 

Cần lưu ý rằng cách giải quyết này không chỉ giới hạn trong các trường hợp enum, nó cũng có thể được sử dụng với các phương pháp nói chung. Ví dụ:

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)). Đã không nhận ra bạn có thể xác định vars dựa trên loại generics. – GoldenJoe

Các vấn đề liên quan