首页 > 解决方案 > 有没有办法使用类似映射的语法在 Scala 的非映射代码块中设置变量?

问题描述

我经常编写代码来评估表达式,然后使用类似于 map 或 fold 表达式的语法将该表达式的结果作为变量传递给下一个代码块。

我想编写的代码看起来就像我们使用 Option 或 Future 所做的那样:

Some("foo") map { upper => s"works with $upper"}

但没有支持地图的对象。

一个很好的例子(但不是唯一的例子)是用喷雾库替换 Json 元素。就像是:

JsObject(upper.fields +
  ("obj" -> JsObject(
    upper.fields("obj").asJsObject { lower: JsObject => lower.fields +
      ("data" -> JsObject(lower.fields("data")))
    }
  ))
) 

有没有办法在不诉诸嵌套匹配的情况下实现这一点?

答案 1:这是一个在 Scala 2.12 中使用鼠标库的示例:

def withMouse(upper: JsObject): JsObject = {
  upper
    .|> { upper => println(upper.compactPrint); upper.fields; }
    .|> { upper => upper + ("obj" ->
      upper("obj").asJsObject.fields
        .|> { lower => JsObject(lower + ("data" ->
          lower("data")
        ))}
    )}
    .|> { newmsg => JsObject(newmsg) }
}

答案 2:这是在 Scala 2.13 中使用ChainingOps库的 .pipe 方法的相同示例

def withPipe(upper: JsObject): JsObject = {
  upper
    .pipe { upper => println(upper.compactPrint); upper.fields; }
    .pipe { upper => upper + ("obj" ->
      upper("obj").asJsObject.fields
        .pipe { lower => JsObject(lower + ("data" ->
          lower("data")
        ))}
    )}
    .pipe { newmsg => JsObject(newmsg) }
}

标签: scala

解决方案


这听起来像你想要pipe()的。

ScalaDocs 页面

import scala.util.chaining._

val times6 = (_: Int) * 6
//times6: Int => Int = $$Lambda$2023/975629453@17143b3b

val i = (1 - 2 - 3).pipe(times6).pipe(scala.math.abs)
//i: Int = 24

推荐阅读