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

时间:2015-10-24 14:26:28

标签: swift scala optional

我有一个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"

现在,只有在可选项不是nil的情况下,如何才能将此项提交给print()

2 个答案:

答案 0 :(得分:5)

我只是映射它

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

对于产生副作用而言,映射并不好,但在Swift中foreach没有Optional。 这也会在Swift 2中产生unused result警告。

如果语义(和警告)错误,您可以随时为foreach定义自己的Optional。这很简单:

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) }

尽可能类似于scala。

答案 1 :(得分:2)

虽然我通常不建议使用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,这基本上是加布里埃尔的答案。