Zip 函数。
Zip 函数在 Swift 的序列中已经定义了。这是一个很好的扩展,可以将其应用在 Optional 类型上。
假设你有一些计算或值是 Optional 类型的。使用 if let
处理它们可能会很繁琐。使用 zip
你可以把容器翻转过来(查看这个 Haskell 中 zip 的文档 来了解类型的转换方式),然后在结果上进行 map
操作。
let userName: String?
let userLast: String?
let userAge: Int?
zip(userName, userLast, userAge)
.map{ (name: String, last: String, age: Int) in
// Working with not optional values
}
允许并发调用多个异步函数,以获取结果的元组。
let (name, age) = await asyncZip(
await asyncGetUserName(),
await asyncGetUserAge()
)
let user = User(name: name, age: age)
与 asyncZip
相同,但最后一个参数是一个函数,可以将这个元组转换成某种类型的实例。
struct User {
let name: String
let age: Int
}
let user: User = asyncZip(
await asyncGetUserName(),
await asyncGetUserAge(),
with: User.init
)
在这个例子中,你可以直接写 User.init
,因为编译器会自动匹配到正确的函数。但是你也可以使用闭包和尾随语法来做任何你需要的事情。
struct User {
let name: String
let age: Int
}
let user: User = asyncZip(
await asyncGetUserName(),
await asyncGetUserAge()
) { (fetchedName: String, fetchedAge: Int) in
User(name: fetchedName, age: fetchedAge)
}
zip
和 zipWith
在 Either 类型上的应用Either
是比 Optional
或 Result
更通用的类型,并且它也定义了 zip
函数(因为它有 map)。如果你想了解更多关于 Either 的信息,请查看这个仓库:EitherSwift Swift Package
let userName: Either<Int,String> = getUserNameOrErrorCode()
let userLastName: Either<Int,String> = getUserLastNameOrErrorCode()
zip(userName, userLastName)
.map { (name: String, last: String) in
// When all are .right cases then you have the values here
}
很多时候,你运行代码是为了对返回值做一些事情。为了简化操作,你可以传递一个函数给 zipWith
。
func validateName (_ s: String) -> Either<Int,String> { ... }
func validateLastName(_ s: String) -> Either<Int,String> { ... }
struct User { let name: String; let lastName: String }
// Given two Eithers when they both are right then returns User.
// Notice as this also returns an Either but luckely this type has a map.
let createUserWhenValid: Either<Int,String>,Either<Int,String>) -> Either<Int,User> = zip(with: User.init)
createUserWhenValid(validateName, validateLastName)
.map { (user: User) in
// Real instance of User type 😎
}
.mapLeft { (errorCodes: [Int]) in
// error codes that were returned as left values
}
如果你想简化在 Swift 中使用 Optionals 的操作,请查看 OptionalAPI Swift Package。它有丰富的文档和测试来展示如何使用它。
这个项目是 🐇🕳 Rabbit Hole Packages Collection 的一部分