9

Clojure 具有“线程宏”->->>. 我很确定可以在 Scala 代码中使用类似的结构来替换以下代码:

var myObj = MyObject(x, y, z)
myObj = transform(myObj, abc)
myObj = transformMore(myObj, def)
myObj = transformYetMore(myObj, bar)

我很想看到一个可行的例子,看看它是否看起来不错。我很确定您不需要在 Scala 案例中使用宏。

4

2 回答 2

4

好问题!我可以想到几个这样的例子可以派上用场。举个例子,我正在处理一个数据集,我想在它上面应用几个函数,同时将结果向前推进,如下所示:

val result: ResultSet = Functions.thread(inputSet)
                                 .andThen(execute(_, executionContext))
                                 .andThen(_.filter(_.nonEmpty))
                                 .andThen(verifyData(_, verificationHelper))
                                 .andThen(_.cache)
                                 .andThen(saveSnapshot)

要在没有线程的情况下编写相同的代码,您将需要嵌套调用或保存中间函数调用的结果。我更喜欢使用上述方法,因为它用更少的行数做同样的事情,从而提高了我的代码的可维护性和可读性。

这是Functions实现此目的的实用程序:

object Functions {
  def thread[T](item: T) = new ThreadFunctor(item)
}

class ThreadFunctor[T](val item: T) {
  def andThen(f: T => T): ThreadFunctor[T] = new ThreadFunctor(f(item))
}

object ThreadFunctor {
  implicit def threadToItem[T](thread: ThreadFunctor[T]): T = thread.item
}
于 2017-02-24T03:55:15.583 回答
-1

clojure 中的线程宏用于解决过度嵌套表达式的问题,因此在 scala 中使用某种线程实用程序非常罕见(尽管原则上是可能的,正如 Stefan 所提到的),因为普通的集合函数很好

def square(x: Int) = x * x
def plusOne(x: Int) = x + 1
List(1,2,3,4).map(square).map(plusOne)

甚至是冗长的:

someCollection.map(...)
              .flatMap(...)
              .filter(...)
              .map(...)
              ...

另一种选择是用于理解(对期权和期货更有用)。如果你对此不满意,你不需要使用宏,有很多关于这种结构的博客文章,例如这个

于 2013-11-14T23:05:37.910 回答