Reputation: 13986
I've notice this behavior in Scala
val list = List[(Int, Int)]()
val set = HashSet[(Int, Int)]()
scala> list :+ (1, 2)
res30: List[(Int, Int)] = List((1,2))
scala> list :+ (1 -> 2)
res31: List[(Int, Int)] = List((1,2))
scala> list :+ 1 -> 2
res32: List[(Int, Int)] = List((1,2))
//Work
// But the same for set not work
set += (1, 2)
<console>:14: error: type mismatch;
found : Int(2)
required: (Int, Int)
set += (1, 2)
//Ok may be += in set mean add all that mean this should work
set += ((1, 2))
set += ((1, 2), (3,4))
// Worked
// But why this one work
set += 1 -> 2
set += (1 -> 2)
set += ((1 -> 2))
Now I'm confuse, could you explain why tuple is not tuple?
scala> (4->5).getClass
res28: Class[_ <: (Int, Int)] = class scala.Tuple2
scala> (4,7).getClass
res29: Class[_ <: (Int, Int)] = class scala.Tuple2$mcII$sp
Upvotes: 3
Views: 61
Reputation: 10111
I think the difference is that HashSet[T]
defines two overloads for +=
, one of which takes a single T
, and the other takes multiple (as a T*
params list). This is inherited from Growable[T]
, and shown here.
List[T].:+
can only take one T
on the right hand side, which is why the compiler works out that it's looking at a tuple, not something that should be turned into a params list.
If you do set += ((1, 2))
then it compiles. Also, val tuple = (1,2); set += x
works too.
See Mario Galicβs answer for why in the case of HashSet[T].+=
the compiler chooses the overload that can't type over the one that can.
Upvotes: 5
Reputation: 48430
The parser stage -Xprint:parser
gives
set.$plus$eq(1, 2)
which seems to resolve to
def += (elem1: A, elem2: A, elems: A*)
that is a method that accepts multiple arguments so compiler probably thinks elem1 = 1
or elem2 = 2
instead of considering (1,2)
as a tuple.
missingfaktor points to SLS 6.12.3 Infix Operations as the explanation
The right-hand operand of a left-associative operator may consist of several arguments enclosed in parentheses, e.g. π;op;(π1,β¦,ππ). This expression is then interpreted as π.op(π1,β¦,ππ).
Now the operator +=
is left-associative because it does not end in :
, and the right-hand operand of +=
consists of several arguments enclosed in parentheses (1,2)
. Therefore, by design, the compiler does not treat (1,2)
as Tuple2
.
Upvotes: 5