通过 Swift 中的函数(或 Init)传播可选值
Propagate an optional through a function (or Init) in Swift
有没有人有(更好的)方法来做到这一点?
假设我有一个可选的 Float
let f: Float? = 2
现在我想将其转换为 Double
let d = Double(f) //fail
这显然会失败,但是有没有办法像使用计算变量那样通过函数链接可选值?我现在正在做的是:
extension Float {
var double: Double { return Double(self) }
}
let d: Double? = f?.double
但我真的不喜欢将强制转换作为计算变量。
我考虑使用的另一个选项是:
public func optionalize<A,B>(_ λ : @escaping (A) -> B) -> (A?) -> B? {
return { (a) in
guard let a = a else { return nil }
return λ(a)
}
}
let d: Double? = optionalize(Double.init)(f)
我意识到我可以保护 'f' 的值来解包它。但是,在许多情况下,可选值将是 returns 可选的函数的参数。这导致守卫中的中间值。如本例所示:
func foo(_ a: String?) throws -> Float {
guard
let a = a,
let intermediate = Float(a)
else { throw.something }
return intermediate
}
此处从 String 到 Float 的转换也可能失败。
至少对于一个计算变量,这个 foo 函数更干净一些
extension String {
var float: Float? { return Float(self) }
}
func foo(_ a: String?) throws -> Float {
guard
let a = a?.float
else { throw.something }
return a
}
我不想重写频繁初始化的可选版本。
任何想法将不胜感激。谢谢!
您可以简单地使用 Optional
的 map(_:)
方法,如果它不是零,它将 return 应用给定转换的包装值,否则它将 return nil
.
let f : Float? = 2
// If f is non-nil, return the result from the wrapped value passed to Double(_:),
// else return nil.
let d = f.map { Double([=10=]) }
正如您在下面的评论中指出的,也可以表示为:
let d = f.map(Double.init)
这是因为map(_:)
需要一个(Float) -> Double
类型的转换函数,而Double
's float initialiser就是这样的函数。
如果转换也 return 是可选的(例如将 String
转换为 Int
时),您可以使用 flatMap(_:)
,它只是传播一个nil
将结果转换回调用者:
let s : String? = "3"
// If s is non-nil, return the result from the wrapped value being passed to the Int(_:)
// initialiser. If s is nil, or Int([=12=]) returns nil, return nil.
let i = s.flatMap { Int([=12=]) }
有没有人有(更好的)方法来做到这一点?
假设我有一个可选的 Float
let f: Float? = 2
现在我想将其转换为 Double
let d = Double(f) //fail
这显然会失败,但是有没有办法像使用计算变量那样通过函数链接可选值?我现在正在做的是:
extension Float {
var double: Double { return Double(self) }
}
let d: Double? = f?.double
但我真的不喜欢将强制转换作为计算变量。
我考虑使用的另一个选项是:
public func optionalize<A,B>(_ λ : @escaping (A) -> B) -> (A?) -> B? {
return { (a) in
guard let a = a else { return nil }
return λ(a)
}
}
let d: Double? = optionalize(Double.init)(f)
我意识到我可以保护 'f' 的值来解包它。但是,在许多情况下,可选值将是 returns 可选的函数的参数。这导致守卫中的中间值。如本例所示:
func foo(_ a: String?) throws -> Float {
guard
let a = a,
let intermediate = Float(a)
else { throw.something }
return intermediate
}
此处从 String 到 Float 的转换也可能失败。 至少对于一个计算变量,这个 foo 函数更干净一些
extension String {
var float: Float? { return Float(self) }
}
func foo(_ a: String?) throws -> Float {
guard
let a = a?.float
else { throw.something }
return a
}
我不想重写频繁初始化的可选版本。
任何想法将不胜感激。谢谢!
您可以简单地使用 Optional
的 map(_:)
方法,如果它不是零,它将 return 应用给定转换的包装值,否则它将 return nil
.
let f : Float? = 2
// If f is non-nil, return the result from the wrapped value passed to Double(_:),
// else return nil.
let d = f.map { Double([=10=]) }
正如您在下面的评论中指出的,也可以表示为:
let d = f.map(Double.init)
这是因为map(_:)
需要一个(Float) -> Double
类型的转换函数,而Double
's float initialiser就是这样的函数。
如果转换也 return 是可选的(例如将 String
转换为 Int
时),您可以使用 flatMap(_:)
,它只是传播一个nil
将结果转换回调用者:
let s : String? = "3"
// If s is non-nil, return the result from the wrapped value being passed to the Int(_:)
// initialiser. If s is nil, or Int([=12=]) returns nil, return nil.
let i = s.flatMap { Int([=12=]) }