Scala:为什么foo(1,2)和foo((1,2))的作用相同?

时间:2016-12-27 03:47:51

标签: scala tuples

说我有Scala功能:

def func(x:(Int,Int)):Int = x._1 + x._2

    func((1,2))  // This works as expected

但是下面的函数调用怎么也能正常工作?

 func(1,2)

我知道函数调用是通过apply方法转向对象但是我甚至无法看到它是如何工作的?

2 个答案:

答案 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