Function composition of methods, functions, and partially applied functions in Scala

守給你的承諾、 提交于 2019-12-04 16:14:32

问题


Somewhat similar to Stack Overflow question Compose and andThen methods, I've been working through Twitter's Scala School tutorial and quickly ran into the same problem that a commenter had (which was great, because I went to bed thinking my problem was solved).

In the tutorial, it defines two methods as such:

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

and while in newer versions of Scala, you can't call compose on them as such: addUmm(_).compose(addAhem(_)), the accepted answer (and some of the other answers seem to hinge upon the fact that addUmm and addAhem are methods, not functions, which creates an issue when trying to call compose. I went to bed satisfied, having successfully run:

scala> ((s: String) => s + " umm").compose((s: String) => s + " ahem")
res0: String => java.lang.String = <function1>

Cool. The issue is that while not being able to compose methods makes some sense, when I the same thing with values I know evaluate to Function1:

val a = (s: String) => s + " umm"
val b = (s: String) => s + " ahem"
val c = a(_).compose(b(_))

Well, that last line coughs up the same error that the original question did, even though they're partial applications of functions this time, not methods. One of the answers in the original question (highly-ranked, but not the accepted answer) seems to hint that it has to do with how the partial application is expanded, what is the explanation?

For a Scala newbie, the fact that the inferencer gets a(_).compose(b(_)) wrong no matter if you explicitly specify _: String both places, but a.compose(b) does is somewhat confusing.


回答1:


a(_).compose(b(_)) expands to x => { a(x).compose(y => b(y) }. Hence the error. What you want is (x => a(x)).compose(y => b(y)). Adding a pair of parentheses fixes this.

scala> (a(_)).compose(b(_: String))
res56: String => java.lang.String = <function1>

scala> res56("hello")
res57: java.lang.String = helloahemumm

But since a and b are functions, you can avoid all this cruft and simply do a compose b.




回答2:


You can use simply 'a compose b'.

scala> val c = a compose b
c: String => java.lang.String = <function1>


来源:https://stackoverflow.com/questions/7683362/function-composition-of-methods-functions-and-partially-applied-functions-in-s

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!