【问题标题】:Compose and andThen methodsCompose 和 andThen 方法
【发布时间】:2011-09-21 19:11:08
【问题描述】:

我正在学习关于 Scala composeandThen 方法的教程 Pattern matching & functional composition。有这样一个例子:

scala> def addUmm(x: String) = x + " umm"
scala> def addAhem(x: String) = x + " ahem"

val ummThenAhem = addAhem(_).compose(addUmm(_))

当我尝试使用它时出现错误:

<console>:7: error: missing parameter type for expanded function ((x$1) => addAhem(x$1).compose(((x$2) => addUmm(x$2))))
   val ummThenAhem = addAhem(_).compose(addUmm(_))
                             ^
<console>:7: error: missing parameter type for expanded function ((x$2) => addUmm(x$2))
   val ummThenAhem = addAhem(_).compose(addUmm(_))
                                               ^
<console>:7: error: type mismatch;
 found   : java.lang.String
 required: Int
     val ummThenAhem = addAhem(_).compose(addUmm(_))

但是,这是可行的:

val ummThenAhem = addAhem _ compose addUmm _

甚至

val ummThenAhem = addAhem _ compose addUmm

教程中的代码有什么问题?后面的表达式和第一个不带括号的表达式不一样吗?

【问题讨论】:

    标签: scala


    【解决方案1】:

    嗯,这个:

    addUhum _
    

    是一个 eta 扩展。它将方法转换为函数。另一方面,这是:

    addUhum(_)
    

    是一个匿名函数。其实就是一个局部函数应用,就是不应用这个参数,整个东西都转换成一个函数。它扩展为:

    x => addUhum(x)
    

    扩展的确切规则有点难以解释,但基本上,函数将从最里面的表达式分隔符“开始”。例外情况是部分函数应用程序,其中“x”被移到函数之外——如果使用_ 代替参数。

    不管怎样,它就是这样展开的:

    val ummThenAhem = x => addAhem(x).compose(y => addUmm(y))
    

    唉,类型推断器不知道 x 或 y 的类型。如果您愿意,您可以使用参数-Ytyper-debug 来查看它所尝试的确切内容。

    【讨论】:

      【解决方案2】:

      addAhem 是一种方法。 compose 方法是在函数上定义的。 addAhem _addAhem 从方法转换为函数,因此可以在其上调用 composecompose 需要一个函数作为它的参数。您通过将addUmm 转换为带有addUmm _ 的函数来为其提供方法addUmm(可以省略下划线,因为编译器可以在知道无论如何都需要函数时自动将方法转换为函数)。所以你的代码:

      addAhem _ compose addUmm
      

      相同
      (addAhem _).compose(addUmm)
      

      但不是

      addAhem(_).compose(addUmm(_))
      

      PS 我没有看你提供的链接。

      【讨论】:

      • 为了完整起见,andThen 示例看起来像:val ahemThenUmm = addAhem(_).andThen(addUmm (_)),而它应该看起来像 val ahemThenUmm1 = (addAhem _).andThen(addUmm)
      • 我不太确定写在圆括号中的部分;编译器不会将方法转换为自动运行,至少对于 Scala 2.10.2 而言。解决方法是将addAhemaddUmm 声明为函数,以便composeandThen 在没有_ 的情况下工作。
      【解决方案3】:

      来自compose 文档:

      在一个新的 Function1 中组合 Function1 的两个实例,使用 this 最后应用的函数。

      所以你应该写

      scala> val ummThenAhem = (addAhem _).compose(addUmm _)
      ummThenAhem: String => java.lang.String = <function1>
      

      addAhemaddUmm 视为部分应用函数(即function1

      scala> addAhem _
      res0: String => java.lang.String = <function1>
      

      【讨论】:

      • 为什么不提供文档链接?
      • “你做”不是答案
      【解决方案4】:

      我相信本教程是为早期版本的 Scala(可能是 2.7.7 或更早版本)编写的。从那时起,编译器发生了一些变化,即对类型系统的扩展,现在导致类型推断在以下方面失败:

      addUhum(_).compose(addAhem(_))
      

      如果你只是写,提升到一个函数仍然可以使用该语法:

      addUhum(_)
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-03-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-10-06
        • 1970-01-01
        • 1970-01-01
        • 2017-03-30
        相关资源
        最近更新 更多