【问题标题】:pipeline operator in ScalaScala中的管道运算符
【发布时间】:2016-01-07 18:16:00
【问题描述】:

我想知道是否可以在magrittr 语言的magrittr 包中定义像%>% 这样的管道运算符。我发现了几个类似的实现,如下所示:

implicit class PipelineContainer[F](val value: F) {
  def |>[G] (f: F => G) = f(value)
}

这样x |> f |> g 就像g(f(x)) 一样工作

现在我希望这个运算符即使在函数接受多个参数时也能工作,在这种情况下,管道参数左侧的值成为右侧函数的第一个参数。例如,x |> f(2) |> g(3) 变为 g(f(x, 2), 3)。我怎样才能在scala中实现这个?它不必与我在这里展示的语法相同,但越简单越好。

【问题讨论】:

    标签: r scala


    【解决方案1】:

    有几个选项。

    一种是内联创建函数。只是有点乱。

    x |> (z=>f(z,2)) |> (z=>g(z,3))
    

    另一种方法是创建可以折叠现有函数的arity 的快捷方法。一般来说,它有很多样板,但第一个很简单:

    implicit class RichPipes[Y](y: Y) {
      def |>[Z](f: Y => Z) = f(y)
      def &>[X, Z](f: (X, Y) => Z): (X => Z) = (x: X) => f(x, y)
    }
    

    然后您可以内联注入其他参数(利用& 的优先级高于| 的事实):

    x |> 2 &> f |> 3 &> g
    

    就我个人而言,我觉得这种风格令人困惑,但编译器可以接受。

    另一种选择是将方法转换为函数以开始(如有必要),然后丰富这些函数以具有部分应用程序辅助方法:

    implicit class RichFunction2[A,B,Z](f: (A,B) => Z) {
      def %(b: B): (A => Z) = (a: A) => f(a,b)
    }
    

    现在可以

    x |> f _ % 2 |> g _ % 3
    

    最后,如果您碰巧能够以不同的方式编写函数,您可以在没有任何额外机制的情况下使其工作,只需在结尾添加_ 让编译器知道您在做什么;不同之处只是应用程序通过了多个参数块中的最后一个:

    def h(y: Int)(x: Int) = x + y
    def i(y: Int)(x: Int) = x * y
    
    x |> h(2) _ |> i(3) _
    

    不过,作为最后的想法,在中途注入参数对于初学者来说可能不是最容易遵循的事情。您可能会考虑与采用不同的工作流程相比,这是否是一种好的编程实践。

    【讨论】:

      猜你喜欢
      • 2011-03-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-06-29
      • 1970-01-01
      • 1970-01-01
      • 2015-02-06
      相关资源
      最近更新 更多