(1)在Scala REPL中定义了两个函数:
scala> def f(s: String) = "f(" + s + ")"
f: (s: String)String
scala> def g(s: String) = "g(" + s + ")"
g: (s: String)String
(2)在没有括号的情况下编写它们可以按预期工作:
scala> f _ compose g _
res18: String => String = <function1>
(3)用括号括起来不会:
scala> f(_).compose(g(_))
<console>:14: error: missing parameter type for expanded function ((x$1) => f(x$1).compose(((x$2) => g(x$2))))
f(_).compose(g(_))
^
<console>:14: error: missing parameter type for expanded function ((x$2) => g(x$2))
f(_).compose(g(_))
^
<console>:14: error: type mismatch;
found : String
required: Int
f(_).compose(g(_))
^
问题1: 有人可以解释原因吗?
问题2: 为什么类型不匹配?为什么Scala期待Int
?
(4)通过使前两个错误消失,带括号的f(_)
周围似乎有所帮助:
scala> (f(_)).compose(g(_))
<console>:14: error: missing parameter type for expanded function ((x$2) => g(x$2))
(f(_)).compose(g(_))
^
问题3: 为什么这些括号有帮助?
问题4: 为什么Scala需要参数类型,即使它们分别在f
和g
中明确定义?
(5)最后,添加参数类型使其起作用:
scala> (f(_)).compose(g(_:String))
res22: String => String = <function1>
您能解释一下发生了什么,并提供替代语法来实现合成吗?
感谢。
答案 0 :(得分:2)
您可以使用魔术评论看到(意外)扩展:
'com.firebase:firebase-client-android:2.3.1'
如您所示,函数文字需要约束约束。 scala> f(_).compose(g(_)) // show
[snip]
val res0 = ((x$1) => f(x$1).compose(((x$2) => g(x$2))))
是eta扩展,与f _
不同,后者是f(_)
的糖。
由于非预期的应用程序x => f(x)
返回一个字符串,这是一个用于索引的f(x$1)
,因此您将获得添加的类型不匹配。
下划线涉及许多SO问题,包括一个规范。