Reputation: 385
Say I have a Scala function :
def func(x:(Int,Int)):Int = x._1 + x._2
func((1,2)) // This works as expected
But how come below function call also works correctly?
func(1,2)
I know about function call being turned to object with apply methods but I am unable to see even then how this works?
Upvotes: 2
Views: 113
Reputation: 2128
If there are no appropriate multi-argument methods and a single appropriate one-argument method, the Scala compiler will try to convert those comma separated arguments into tuples.
The type of the argument x
to your func
method is (Int, Int)
, which is a syntactic sugar for Tuple2[Int, Int]
. So the signature of func
method is actually func(Tuple2[Int, Int])
.
You invoke it as func(1, 2)
, but there's no method with signature func(Int, Int)
defined in the scope, so the compiler will roughly translate the invocation to func(Tuple2(1, 2))
, which matches the signature of your method. So this kind of invocation will work, but can lead to unexpected results (it's not hard to see why).
EDIT: Also see this question for additional reading.
Upvotes: 2
Reputation: 14217
This is a syntax of scala:
(x_1 , … , x_n),((x_1 , … , x_n))
is a shorthand for `Tuple$n$($x_1 , … , x_n$)
check this Tuples, revised.
and also when check the generated bytecode:
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
}
we can see this is transformed by compiler: new #32 // class scala/Tuple2$mcII$sp
and I think this is equivalent to Function.untupled
, example:
scala> Function.untupled(func _)(1, 2)
res1: Int = 3
Upvotes: 0