函数式Swift——枚举

关于枚举

OC中的枚举与Swift中的枚举

Objective-C中的枚举类型类似于NSASCIIStringEncodingNSNEXTSTEPStringEncodingNSJapaneseEUCStringEncodingNSUTF8StringEncoding酱婶儿的,用起来也是比较麻烦。

Swift中,枚举出现的方式已经没有那么粗暴了,而是像UIViewContentMode.BottomUIViewAnimationOptions.Autoreverse这样比较温柔的方式,实际使用的时候还支持像.Bottom.Autoreverse这样的文艺使用方法。

而且在我们实际使用枚举值的时候,枚举的定义还可以加入关联值泛型等概念,这使得枚举的实际使用价值更加高了

关联值

枚举中加入关联值的作用在于:我们在传递一个枚举值的时候,还可以同时传递一个(或多个)规定的关联值,这样我们可以通过媒体传递更多的信息。
比如我们要实现一个网络请求,请求的结果有成功失败

我们定义一个网络请求的结果枚举:

1
2
3
4
enum Result {
case Success
case Failure
}

我们拿到结果之后,可以知道这个结果是否成功了。但是成功之后,我的网络请求返回的数据呢?失败之后,我我是为什么失败了呢?这样只能从其他方式再去获取了,能不能值传递一个结果就能拿到我想要的这些东西呢?

似乎关联值可以:

1
2
3
4
enum Result {
case Success(String)
case Failure(NSError)
}

这样我们就可以这样来使用这个结果:

1
2
3
4
5
6
7
8
9
10
11
12
13
func printResult(result:Result) {
switch result {
case .Success(let data):
print(data)
case .Failure(let error):
print(error)
}
}
let a = Result.Success("Hello World")
let b = Result.Failure(NSError(domain: "test Error", code: 404, userInfo: ["1234567":"abcdefg"]))
printResult(a) // Hello World
printResult(b) // Error Domain=test Error Code=404 "(null)" UserInfo={1234567=abcdefg}

看起来还不错,但是每次想要取值都去switch-case一下还是太麻烦了,我们将它改成.一下就能取值的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
enum Result {
case Success(String)
case Failure(NSError)
var data: String? {
switch self {
case .Success(let data):
return data
case .Failure:
return nil
}
}
var error: NSError? {
switch self {
case .Failure(let error):
return error
case .Success:
return nil
}
}
}
print("\(a.data)"+" "+"\(a.error)") //Optional("Hello World") nil
print("\(b.data)"+" "+"\(b.error)") //nil Optional(Error Domain=test Error Code=404 "(null)" UserInfo={1234567=abcdefg})

添加泛型

现在,一个网络请求的结果枚举就完成了,我现在还需要一个数据库请求的结果枚举,功能都差不多,只是请求成功后数据类型有点不一样,像下面这样在这个枚举中加入泛型就可以拿来用了:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
enum Result<Data,Error:ErrorType> { //声明枚举时添加类型签名
//enum Result {
case Success(Data)//使用泛型作为关联值
case Failure(Error)
// case Success(String)
// case Failure(NSError)
var data: Data? {//在成员和方法中也使用泛型
// var data: String? {
switch self {
case .Success(let data):
return data
case .Failure:
return nil
}
}
var error: Error? {
// var error: NSError? {
switch self {
case .Failure(let error):
return error
case .Success:
return nil
}
}
}

数据类型中的代数学

同构

“比较直观的解释是,如果两个类型 A 和 B 在相互转换时不会丢失任何信息,那么它们就是同构的。”

摘录来自: Chris Eidhof. “函数式 Swift”。 iBooks.

通过枚举和泛型可以定义许多代数数据类型,具有某些数学运算的特性,比如加法乘法微分积分