【问题标题】:Propagate an optional through a function (or Init) in Swift通过 Swift 中的函数(或 Init)传播可选项
【发布时间】:2016-10-19 21:06:04
【问题描述】:

有没有人有(更好的)方法来做到这一点?

假设我有一个可选的浮动

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' 的值来解开它。然而,在许多情况下,可选值将是返回可选值的函数的参数。这导致防护中的中间值。如本例所示:

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
}

我不想重写频繁初始化的可选版本。

任何想法将不胜感激。谢谢!

【问题讨论】:

标签: swift optional


【解决方案1】:

您可以简单地使用Optionalmap(_:) 方法,如果它是非零,它将返回应用给定转换的包装值,否则它将返回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($0) }

正如您在下面的 cmets 中指出的那样,也可以这样说:

let d = f.map(Double.init)

这是因为map(_:) 在这种情况下需要(Float) -&gt; Double 类型的转换函数,而Double's float initialiser 就是这样的函数。

如果转换还返回一个可选值(例如在将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($0) returns nil, return nil.
let i = s.flatMap { Int($0) }

【讨论】:

  • 谢谢!我不知道为什么我没有想到这个!唯一的变化是 f.map(Double.init) 就像一个风格的东西;)
  • @MrFlynn 当然,感谢您提到这一点 - 我已经编辑了我的答案以包含它。尽管请注意,有时编译器会希望您通过说 map(XYZ.init(_:)) 来消除初始化程序的歧义——那时我绝对认为闭包语法更简洁:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-04-27
  • 2021-12-22
  • 2020-07-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多