撰写和然后方法
我正在按照Scala andThen
模式匹配和function组合以及和方法。 有这样一个例子:
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
教程中的代码有什么问题? 后一种expression方式与没有括号的第一种expression方式是否相同?
addAhem
是一种方法。 compose
方法是在函数上定义的。 addAhem _
将addAhem
从方法转换为函数,因此可以调用它。 compose
期望的function,因为它的论点。 通过将addUmm
转换为带有addUmm _
的函数,您正在给它一个方法addUmm
(下划线可以省略,因为编译器可以在知道某个函数预期的时候自动将函数转换为函数)。 所以你的代码:
addAhem _ compose addUmm
是相同的
(addAhem _).compose(addUmm)
但不是
addAhem(_).compose(addUmm(_))
PS我没有看你提供的链接。
那么这个:
addUhum _
是一个eta扩展。 它将方法转换为函数。 另一方面,这个:
addUhum(_)
是一个匿名函数。 实际上,它是一个部分函数应用程序,因为这个参数没有被应用,整个事物被转换成一个函数。 它扩展到:
x => addUhum(x)
扩展的确切规则有点难以解释,但是,基本上,函数将在最里面的expression式分隔符处“开始”。 部分函数应用程序例外,其中“x”被移到函数之外 – 如果_
用于代替参数。
无论如何,这是如何扩大:
val ummThenAhem = x => addAhem(x).compose(y => addUmm(y))
唉,types推断器不知道x或y的types。 如果你愿意的话,你可以看到它使用参数-Ytyper-debug
尝试。
从compose
文件:
在新的Function1中组合Function1的两个实例,并最后应用该函数。
所以你应该写
scala> val ummThenAhem = (addAhem _).compose(addUmm _) ummThenAhem: String => java.lang.String = <function1>
将addAhem
和addUmm
作为部分应用函数(即function1
)
scala> addAhem _ res0: String => java.lang.String = <function1>
我相信本教程是为早期版本的Scala编写的(可能是2.7.7或更早的版本)。 从那以后,编译器发生了一些变化,即对types系统的扩展,现在会导致types推断失败:
addUhum(_).compose(addAhem(_))
如果你只写:
addUhum(_)