# Scala - Operators

Last Updated: 2021-11-19

## 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> x ++ y
res15: List[Int] = List(1, 2, 3, 4)

scala> x ++: y
``````

### 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)
``````