如何在可选类型上执行闭包而不展开它



我有一个Swift可选类型,我想把一个转换链到它(map),并最终将它传递给一个闭包来打印它。

我想避免打开(使用!)可选类型,因为我不想执行闭包,除非我们在可选中有东西。

在Scala中我们使用foreach作为返回Unit的map

val oi = Option(2)
oi.map(_+1).foreach(println)

在Swift中,我只得到直到增量(和转换为字符串)

let oi:Int? = 1
let oiplus = oi.map({$0 + 1}).map({String($0)})
// now we have "2"

现在我如何给print()只在可选的情况下不是nil?

我将映射到它上面

let oi: Int? = 1
let oiplus = oi.map{ $0 + 1 }.map { String($0) }
oiplus.map { print($0) }

可能不太适合映射产生副作用,但是Swift中没有foreach对应Optional。这也会在Swift 2中产生unused result警告。

如果语义(和警告)错误,您可以始终为Optional定义自己的foreach。非常简单:

extension Optional {
  func forEach(f: Wrapped -> Void) {
    switch self {
    case .None: ()
    case let .Some(w): f(w)
    }
  }
}

let oi: Int? = 1
let oiplus = oi.map{ $0 + 1 }.map { String($0) }
oiplus.forEach { print($0) }

虽然我通常不建议使用map的副作用,但在这种情况下,我相信它是最干净的Swift。

_ = oiplus.map{ print($0) }

现在有一个SequenceType.forEach方法明确地解决这个问题,但Optional不是SequenceType。你当然可以扩展Optional来添加一个类似forEach的方法(我可能会在Swift中称之为apply)。

值得注意的是,这只是避免了if-lit,它几乎不再:
if let o = oiplus { print(o) }

但不可否认的是,它不像:

那样链接得很好。
_ = oi
    .map { $0 + 1 }
    .map { print($0) }

参见http://www.openradar.me/23247992,这基本上是Gabriele的答案。

最新更新