如何用较少的括号在Scala中编写f(g(h(x)))?

时间:2011-08-29 06:31:59

标签: scala coding-style syntax functional-programming

表达式

ls map (_ + 1) sum

很可爱,因为它们是从左到右而不是嵌套。但是如果有问题的函数是在类之外定义的,那就不那么漂亮了。

关注an example我尝试了

final class DoublePlus(val self: Double) {
    def hypot(x: Double) = sqrt(self*self + x*x)
}

implicit def doubleToDoublePlus(x: Double) =
    new DoublePlus(x)

除了

之外,我可以正常工作
  1. 为一种方法打字很多

  2. 您需要提前知道您想以这种方式使用

  3. 是否有解决这两个问题的技巧?

5 个答案:

答案 0 :(得分:13)

您可以在函数对象上调用andThen

(h andThen g andThen f)(x)

你不能直接在方法上调用它,所以也许你的h需要成为(h _)才能将方法转换为部分应用的函数。编译器会自动将后续方法名称转换为函数,因为andThen方法接受Function参数。

你也可以使用pipe operator |>写下这样的内容:

x |> h |> g |> f

答案 1 :(得分:2)

使用隐式转换(这是您使用doubleToDoublePlus所做的事情)丰富现有的类/接口是关于API设计的,当某些类不在您的控制之下时。我不建议只是为了节省一些击键或少一些括号。因此,如果能够键入val h = d hypot x很重要,那么额外的击键不应该是一个问题。 (可能存在对象分配问题,但这有所不同)。

标题和您的示例也不匹配:

f(g(h(x)))可以重写为f _ compose g _ compose h _ apply x如果您关注的是括号,或f compose g compose h apply x如果f,g,h是功能对象而不是 DEF

ls map (_ + 1) sum不是你所说的嵌套调用,所以我不确定它与标题的关系。虽然它可以可爱使用,但是图书馆/语言设计师经过了很多努力才能使它易于使用而且引人注目并不简单(比你的 hypot更复杂示例)。

答案 2 :(得分:2)

def fgh (n: N) = f(g(h(n))) 
val m = fgh (n) 

答案 3 :(得分:0)

也许这样,观察一下如何提供:

def组成[A,B,C](f:B => C,g:A => B):A => C =(a:A)=> F(G(A))

基本上像上面的答案将所需的功能组合到一个中间的功能,然后您可以轻松地使用地图。

答案 4 :(得分:0)

Scala 2.13开始,标准库提供了链接操作pipe,可用于转换/传递具有所需功能的值。

因此,使用多个pipe,我们可以构建一个pipeline,正如您的问题的标题所述,它可以将括号的数量减至最少:

import scala.util.chaining._

x pipe h pipe g pipe f