scala 组合和然后方法
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/7505304/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Compose and andThen methods
提问by lowercase
I'm following the tutorial Pattern matching & functional compositionon Scala composeand andThenmethods. There's such an example:
我正在关注Scala和方法上的模式匹配和功能组合教程。有这样一个例子:composeandThen
scala> def addUmm(x: String) = x + " umm"
scala> def addAhem(x: String) = x + " ahem"
val ummThenAhem = addAhem(_).compose(addUmm(_))
When I try to use it I get an error:
当我尝试使用它时,出现错误:
<console>:7: error: missing parameter type for expanded function ((x) => addAhem(x).compose(((x) => addUmm(x))))
val ummThenAhem = addAhem(_).compose(addUmm(_))
^
<console>:7: error: missing parameter type for expanded function ((x) => addUmm(x))
val ummThenAhem = addAhem(_).compose(addUmm(_))
^
<console>:7: error: type mismatch;
found : java.lang.String
required: Int
val ummThenAhem = addAhem(_).compose(addUmm(_))
However, this works:
但是,这有效:
val ummThenAhem = addAhem _ compose addUmm _
or even
甚至
val ummThenAhem = addAhem _ compose addUmm
What's wrong with the code in the tutorial? Isn't the latter expression the same as the first one without parenthesis?
教程中的代码有什么问题?后一个表达式不是和第一个没有括号的表达式一样吗?
采纳答案by agilesteel
addAhemis a method. composemethod is defined on functions. addAhem _converts addAhemfrom method to function, so composecan be called on it. composeexpects a function as it's argument. You are giving it a method addUmmby converting addUmminto a function with addUmm _(The underscore can be left out because the compiler can automatically convert a method into a function when it knows that a function is expected anyway). So your code:
addAhem是一种方法。compose方法是在函数上定义的。从方法addAhem _转换addAhem为函数,因此compose可以对其进行调用。compose期望一个函数作为它的参数。您addUmm通过将方法转换addUmm为函数addUmm _(可以省略下划线,因为编译器可以在知道无论如何需要函数时自动将方法转换为函数)来为其提供方法。所以你的代码:
addAhem _ compose addUmm
is the same as
是相同的
(addAhem _).compose(addUmm)
but not
但不是
addAhem(_).compose(addUmm(_))
PS I didn't look at the link you provided.
PS我没有看你提供的链接。
回答by Daniel C. Sobral
Well, this:
嗯,这个:
addUhum _
is an eta expansion. It converts methods into functions. On the other hand, this:
是 eta 展开。它将方法转换为函数。另一方面,这:
addUhum(_)
is an anonymous function. In fact, it is a partial function application, in that this parameter is not applied, and the whole thing converted into a function. It expands to:
是匿名函数。其实就是一个偏函数的应用,没有应用这个参数,整个东西都转成了一个函数。它扩展为:
x => addUhum(x)
The exact rules for expansion are a bit difficult to explain, but, basically, the function will "start" at the innermost expression delimiter. The exception is partial function applications, where the "x" is moved outside the function -- if _is used in place of a parameter.
扩展的确切规则有点难以解释,但基本上,函数将从最里面的表达式定界符“开始”。例外是部分函数应用程序,其中“x”移动到函数之外——if_用于代替参数。
Anyway, this is how it expands:
无论如何,这就是它的扩展方式:
val ummThenAhem = x => addAhem(x).compose(y => addUmm(y))
Alas, the type inferencer doesn't know the type of x or y. If you wish, you can see exactly what it tried using the parameter -Ytyper-debug.
唉,类型推断器不知道 x 或 y 的类型。如果您愿意,您可以使用参数 确切地看到它尝试了什么-Ytyper-debug。
回答by 4e6
From composedocumentation:
从compose文档:
Composes two instances of Function1 in a new Function1, with this function applied last.
在新的 Function1 中组合 Function1 的两个实例,最后应用此函数。
so you should write
所以你应该写
scala> val ummThenAhem = (addAhem _).compose(addUmm _)
ummThenAhem: String => java.lang.String = <function1>
to treat addAhemand addUmmas partially applied functions (i.e function1)
处理addAhem和addUmm作为部分应用的功能(即function1)
scala> addAhem _
res0: String => java.lang.String = <function1>
回答by axel22
I believe the tutorial was written for an earlier version of Scala (probably 2.7.7 or earlier). There have been some changes in the compiler since then, namely, extensions to the type system, which now cause the type inferencing to fail on the:
我相信本教程是为 Scala 的早期版本(可能是 2.7.7 或更早版本)编写的。从那时起,编译器发生了一些变化,即对类型系统的扩展,现在导致类型推断在以下情况下失败:
addUhum(_).compose(addAhem(_))
The lifting to a function still works with that syntax if you just write:
如果你只写:
addUhum(_)

