Scala - Operators
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
<%: view bound
>:: 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+
) 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+
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)