撰写和然后方法

我正在按照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> 

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

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

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

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

如果你只写:

 addUhum(_)