这会产生一个匿名函数,正如您所期望的那样(f是一个带有三个参数的函数):
f(_, _, _)
我不明白为什么这不编译,而是给出“缺少参数类型”错误:
f(_, _, 27)
相反,我需要明确指定下划线的类型。 Scala不应该能够推断它们,因为它知道函数f的参数类型是什么吗?
答案 0 :(得分:18)
以下参考资料是Scala Language Specification
考虑以下方法:
def foo(a: Int, b: Int) = 0
Eta Expansion可以将其转换为(Int, Int) => Int
类型的值。如果符合以下条件,则调用此扩展:
a)_
用于代替参数列表(方法值(§6.7))
val f = foo _
b)省略参数列表,期望的表达式是函数类型(§6.25.2):
val f: (Int, Int) => Int = foo
c)每个参数都是_
(匿名函数的占位符语法的special case(§6.23))
val f = foo(_, _)
表达式foo(_, 1)
不符合Eta Expansion的条件;它只是扩展到(a) => foo(a, 1)
(§6.23)。常规类型推断不会试图找出a: Int
。
答案 1 :(得分:8)
如果您正在考虑部分应用,我认为这只能通过多个参数列表来实现(而您只有一个):
def plus(x: Int)(y: Int) = x + y //x and y in different parameter lists
val plus10 = plus(10) _ //_ indicates partial application
println(plus10(2)) //prints 12
你的例子很有趣,因为我完全不知道你描述的语法,看来你可以用一个参数列表进行部分应用:
scala> def plus2(x: Int, y: Int) = x + y
plus2: (x: Int,y: Int)Int
scala> val anon = plus2(_,_)
anon: (Int, Int) => Int = <function2>
scala> anon(3, 4)
res1: Int = 7
因此编译器可以清楚地推断类型Int
!
scala> val anon2 = plus2(20,_)
<console>:5: error: missing parameter type for expanded function ((x$1) => plus2(20, x$1))
val anon2 = plus2(20,_)
^
嗯,奇怪!我似乎无法使用单个参数列表进行部分应用。但是如果我声明第二个参数的类型,我可以部分应用!
scala> val anon2 = plus2(20,_: Int)
anon2: (Int) => Int = <function1>
scala> anon2(24)
res2: Int = 44
编辑 - 我要观察的一件事是,似乎以下两个缩写是等价的,在这种情况下,它更明显,这不是一个“部分应用程序”,而更像是一个“函数指针”
val anon1 = plus2(_,_)
val anon2 = plus2 _
答案 2 :(得分:1)
我认为这是因为重载使编译器无法推断出类型:
scala> object Ashkan { def f(a:Int,b:Int) = a; def f(a:Int,b:String) = b; }
defined object Ashkan
scala> Ashkan.f(1,2)
res45: Int = 1
scala> Ashkan.f(1,"Ashkan")
res46: String = Ashkan
scala> val x= Ashkan.f _
<console>:11: error: ambiguous reference to overloaded definition,
both method f in object Ashkan of type (a: Int, b: String)String
and method f in object Ashkan of type (a: Int, b: Int)Int
match expected type ?
val x= Ashkan.f _
^
scala> val x= Ashkan.f(_,_)
<console>:11: error: missing parameter type for expanded function ((x$1, x$2) => Ashkan.f(x$1, x$2))
val x= Ashkan.f(_,_)
^
<console>:11: error: missing parameter type for expanded function ((x$1: <error>, x$2) => Ashkan.f(x$1, x$2))
val x= Ashkan.f(_,_)
^
scala> val x= Ashkan.f(_,"Akbar")
<console>:11: error: missing parameter type for expanded function ((x$1) => Ashkan.f(x$1, "Akbar"))
val x= Ashkan.f(_,"Akbar")
^
scala> val x= Ashkan.f(1,_)
<console>:11: error: missing parameter type for expanded function ((x$1) => Ashkan.f(1, x$1))
val x= Ashkan.f(1,_)
^
scala> val x= Ashkan.f(1,_:String)
x: String => String = <function1>
答案 3 :(得分:-4)
我觉得这是所有代码转换产生的边界情况之一,因为这涉及创建一个匿名函数,该函数将调用指向原始方法。该类型用于外部匿名函数的参数。实际上,您可以指定任何子类型,即
val f = foo(_: Nothing, 1)
即使这样也会编译