如何在不解包的情况下对可选类型执行闭包?

How to execute a closure on an optional type without unwrapping it?

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

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

在 Scala 中,我们使用 foreach 作为 map 即 returns 的单位。

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

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

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

现在我如何将它提供给 print() 只有在可选不为零的情况下?

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

_ = oiplus.map{ print([=10=]) }

现在有一个 SequenceType.forEach 方法明确针对这个问题,但是 Optional 不是 SequenceType。您当然可以扩展 Optional 以添加类似 forEach 的方法(我可能会在 Swift 中将其称为 apply)。

值得注意的是,这只是避免了 if-lit,几乎不再是:

if let o = oiplus { print(o) }

但不可否认,它的链接不如:

_ = oi
    .map { [=12=] + 1 }
    .map { print([=12=]) }

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

我会在上面映射

let oi: Int? = 1
let oiplus = oi.map{ [=10=] + 1 }.map { String([=10=]) }
oiplus.map { print([=10=]) }

可以说映射会产生副作用并不好,但是 Swift 中的 Optional 没有 foreach。 这也会在 Swift 中产生 unused result 警告 2.

如果语义(和警告)困扰您,您可以随时为 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{ [=12=] + 1 }.map { String([=12=]) }
oiplus.forEach { print([=12=]) }

尽可能类似于scala。