scala - `doto` 用于 Scala

标签 scala

Clojure 提供了一个名为 doto 的宏它接受它的参数和一个函数列表,并基本上调用每个函数,在(评估的)参数之前:

(doto (new java.util.HashMap) (.put "a" 1) (.put "b" 2))
-> {a=1, b=2}

有没有办法在 Scala 中实现类似的东西?我设想具有以下形式的东西:
val something =
  doto(Something.getInstance) {
    x()
    y()
    z()
  }

这将相当于
val something = Something.getInstance
something.x()
something.y()
something.z()

是否可以使用 scala.util.DynamicVariable ?

请注意,对于工厂方法,例如 Something.getInstance , 不可能使用通用的 Scala 模式
val something =
  new Something {
    x()
    y()
    z()
  }

最佳答案

我认为库中没有内置这样的东西,但您可以很容易地模仿它:

def doto[A](target: A)(calls: (A => A)*) =
  calls.foldLeft(target) {case (res, f) => f(res)}

用法:
scala> doto(Map.empty[String, Int])(_ + ("a" -> 1), _ + ("b" ->2))
res0: Map[String,Int] = Map(a -> 1, b -> 2)

scala> doto(Map.empty[String, Int])(List(_ + ("a" -> 1), _ - "a", _ + ("b" -> 2)))
res10: Map[String,Int] = Map(b -> 2)

当然,只要您的函数返回正确的类型,它就可以工作。在您的情况下,如果该函数只有副作用(不是那么“scalaish”),您可以更改 doto并使用 foreach而不是 foldLeft :
def doto[A](target: A)(calls: (A => Unit)*) =
  calls foreach {_(target)}

用法:
scala> import collection.mutable.{Map => M}
import collection.mutable.{Map=>M}

scala> val x = M.empty[String, Int]
x: scala.collection.mutable.Map[String,Int] = Map()

scala> doto(x)(_ += ("a" -> 1), _ += ("a" -> 2))

scala> x
res16: scala.collection.mutable.Map[String,Int] = Map(a -> 2)

关于scala - `doto` 用于 Scala,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11118881/

相关文章:

scala - Scala 项目中使用 sbt 与 maven 的优缺点

scala - sc.textFile Scala错误

java - 使用 Java/Scala 创建文档的格式化 PNG 'pages'

scala - lit(0) 和 lit(1) 在 Scala/Spark 聚合函数中做什么?

scalaz:如何处理验证中的不同错误类型?

scala - 如何用Scala中另一个Seq的值替换一个Seq中的值?

linux - 如何将多行粘贴到 scala stdIn 进程的命令行提示符?

Scala Multiple Future 包含在 Try 中

scala - 如何将scala向量转换为spark ML向量?

java - 使用 Redis 在 Java/Scala 中实现持久计划作业