# Scala - Operators

Updated: 2018-12-08

## Left Associative vs Right Associative

• Left: a op b = a.op(b)
• Right: a op b = b.op(a)

All:-ending operators are right associative

## Operators

### ->: Create Tuple2

scala> val a = 1 -> 2
a: (Int, Int) = (1,2)

scala> val b = Tuple2(1,2)
b: (Int, Int) = (1,2)

scala> a == b
res30: Boolean = true

Create key-value pairs for Map

scala> Map(1 -> 2, 3 -> 4)
res32: scala.collection.immutable.Map[Int,Int] = Map(1 -> 2, 3 -> 4)

### _*

arbitrary long sequences; vararg expansion

### <:: upper type bound

T <: A declares that type variable T refers to a subtype of type A

### >:: lower bound

The term T >: A expresses that the type parameter T or the abstract type T refer to a supertype of type A.

### +T

declares type T to be used only in covariant positions.

### -T

declare T to be used only in contravariant positions.

### +: prepend(elem+:list) right-associative

scala> 1 +: List(1,2)
res21: List[Int] = List(1, 1, 2)

scala> (1 to 5).foldLeft(List[Int]())((a, b) => (b+:a))
res57: List[Int] = List(5, 4, 3, 2, 1)

scala> (1 to 5).foldLeft(List[Int]())((a, b) => b :: a).reverse
res45: List[Int] = List(1, 2, 3, 4, 5)

scala> (1 to 5) filter {_%2 == 0}
res46: scala.collection.immutable.IndexedSeq[Int] = Vector(2, 4)

### :+ append(list:+elem)

scala> List(1,2) :+ 3
res23: List[Int] = List(1, 2, 3)

scala> (1 to 5).foldLeft(List[Int]())((a, b) => (a:+b))
res54: List[Int] = List(1, 2, 3, 4, 5)

scala> 1 +: List(2,3,4) :+ 5
res7: List[Int] = List(1, 2, 3, 4, 5)

### :: prepend an element to a list(elem::list) right-associative

scala> 1 :: List(2,3)
res18: List[Int] = List(1, 2, 3)

scala> List(2,3).::(1)
res19: List[Int] = List(1, 2, 3)
scala> (1 to 5).foldLeft(List[Int]())((a, b) => b :: a)
res25: List[Int] = List(5, 4, 3, 2, 1)

::, +::: corollary operations

### ::: vs ++: concatenate 2 Lists

scala> (1 to 5).toList ::: (6 to 10).toList
res67: List[Int] = List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
scala> val x = List(1, 2)
x: List[Int] = List(1, 2)

scala> val y = List(3, 4)
y: List[Int] = List(3, 4)

The two operators are equivalent if used as operators

scala> x ++ y
res9: List[Int] = List(1, 2, 3, 4)

scala> x ::: y
res10: List[Int] = List(1, 2, 3, 4)

However if used as method calls, they are different

scala> x.++(y)
res8: List[Int] = List(1, 2, 3, 4)

scala> x.:::(y)
res11: List[Int] = List(3, 4, 1, 2)

### ++ vs ++:

• ++: left operand determines the type of the resulting collection
• ++:: right operand determines the type of the resulting collection
scala> val x = List(1, 2)
x: List[Int] = List(1, 2)

scala> val y = scala.collection.mutable.LinkedList(3,4)
y: scala.collection.mutable.LinkedList[Int] = LinkedList(3, 4)

scala> x ++ y
res15: List[Int] = List(1, 2, 3, 4)

scala> x ++: y
res16: scala.collection.mutable.LinkedList[Int] = LinkedList(1, 2, 3, 4)

### More Examples

scala> val a = Array(1,2,3)
a: Array[Int] = Array(1, 2, 3)

scala> val b = Array(4,5,6)
b: Array[Int] = Array(4, 5, 6)

scala> a ++ b
res1: Array[Int] = Array(1, 2, 3, 4, 5, 6)

scala> a :+ b
res2: Array[Any] = Array(1, 2, 3, Array(4, 5, 6))

scala> a +: b
res3: Array[Any] = Array(Array(1, 2, 3), 4, 5, 6)

:: prepend an element to a list(elem::list)

scala> (1 to 5).foldLeft(List[Int]())((a, b) => b :: a)
res25: List[Int] = List(5, 4, 3, 2, 1)

:+ append(list:+elem)

scala> (1 to 5).foldLeft(List[Int]())((a, b) => (a:+b))
res54: List[Int] = List(1, 2, 3, 4, 5)

+: prepend(elem+:list)

scala> (1 to 5).foldLeft(List[Int]())((a, b) => (b+:a))
res57: List[Int] = List(5, 4, 3, 2, 1)

scala> (1 to 5).foldLeft(List[Int]())((a, b) => b :: a).reverse
res45: List[Int] = List(1, 2, 3, 4, 5)

scala> (1 to 5) filter {_%2 == 0}
res46: scala.collection.immutable.IndexedSeq[Int] = Vector(2, 4)

::: concatenate 2 Lists

scala> (1 to 5).toList ::: (6 to 10).toList
res67: List[Int] = List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)