说我有Scala功能:
def func(x:(Int,Int)):Int = x._1 + x._2
func((1,2)) // This works as expected
但是下面的函数调用怎么也能正常工作?
func(1,2)
我知道函数调用是通过apply方法转向对象但是我甚至无法看到它是如何工作的?
答案 0 :(得分:2)
如果没有合适的多参数方法和单个适当的单参数方法,Scala编译器将尝试将这些以逗号分隔的参数转换为元组。
x
方法的参数func
的类型为(Int, Int)
,这是Tuple2[Int, Int]
的语法糖。因此func
方法的签名实际上是func(Tuple2[Int, Int])
。
您将其作为func(1, 2)
调用,但是在作用域中没有定义签名func(Int, Int)
的方法,因此编译器会将调用粗略地转换为func(Tuple2(1, 2))
,其匹配你的方法的签名。所以这种调用会起作用,但会导致意想不到的结果(不难看出原因)。
编辑:另请参阅this问题以获取更多信息。
答案 1 :(得分:0)
这是 scala :
的语法的简写
(x_1 , … , x_n),((x_1 , … , x_n))
是`元组$ n $($ x_1,...,x_n $)
检查此Tuples, revised。
以及检查生成的字节码:
scala> def bar(x: Int, y: Int) = func(x, y)
scala> :javap -c bar
Compiled from "<console>"
public class $line5.$read$$iw$$iw$ {
public static $line5.$read$$iw$$iw$ MODULE$;
public static {};
Code:
0: new #2 // class $line5/$read$$iw$$iw$
3: invokespecial #23 // Method "<init>":()V
6: return
public int bar(int, int);
Code:
0: getstatic #30 // Field $line3/$read$$iw$$iw$.MODULE$:L$line3/$read$$iw$$iw$;
3: new #32 // class scala/Tuple2$mcII$sp
6: dup
7: iload_1
8: iload_2
9: invokespecial #35 // Method scala/Tuple2$mcII$sp."<init>":(II)V
12: invokevirtual #39 // Method $line3/$read$$iw$$iw$.func:(Lscala/Tuple2;)I
15: ireturn
public $line5.$read$$iw$$iw$();
Code:
0: aload_0
1: invokespecial #42 // Method java/lang/Object."<init>":()V
4: aload_0
5: putstatic #44 // Field MODULE$:L$line5/$read$$iw$$iw$;
8: return
}
我们可以看到这是由编译器转换的:new #32 // class scala/Tuple2$mcII$sp
我认为这相当于Function.untupled
,例如:
scala> Function.untupled(func _)(1, 2)
res1: Int = 3