Scala – building lists

All lists are built from two fundamental building blocks, Nil and :: (pronounced “cons”).

Nil represents the empty list.

val empty_1:List[Nothing]=Nil
println(empty_1)

The infix operator, ::, expresses list extension at the front.

val lstNested: List[List[Int]] = List(List(1, 2, 3), List(4, 5, 6))

can be written as

val lstNested_1: List[List[Int]] = (1::(2::(3::Nil))) ::
  (4::(5::List(6)))::Nil

 

object Lists_Operations extends App {


  val v1: List[Int] = List(1, 2, 3)
  val v1_1: List[Int] = 1 :: (2 :: (3 :: Nil))

  println(v1)
  println(v1_1)

  val lstNothing: List[Nothing] = List()
  val lstString: List[String] = List()
  val empty = Nil
  println(empty)

  val lstNested: List[List[Int]] = List(List(1, 2, 3), List(4, 5, 6))
  println(lstNested)

  val lstNested_1: List[List[Int]] = (1 :: (2 :: (3 :: Nil))) ::
    (4 :: (5 :: List(6))) :: Nil

  println(lstNested_1)

  val lstNested_2: List[List[Int]] = (1 :: (2 :: (3 :: Nil))) ::
    (4 :: (5 :: (6 :: Nil))) :: Nil

  println(lstNested_2)
}

Scala – List element datatypes

The list type in Scala is covariant. This means that for each pair of types S and T, if S is a subtype of T, then List[S] is a subtype of List[T].

Nothing is the bottom type in Scala’s class hierarchy. It is a subtype of every other Scala type. Because lists are covariant, it follows that List[Nothing] is a subtype of List[T], for any type T.

object Lists_Operations extends App {

  val lstNested: List[List[Int]] = List(List(1, 2, 3), List(4, 5, 6))
  println(lstNested)

  val lstNothing: List[Nothing] = List()
  val lstString: List[String] = List()

}

Scala – Difference between Classes and traits

Difference  – 1

class Employee(x: Int, y: Int) {}

trait Learning (x: Int, y: Int) {} // Does not compile

Difference –  2

In classes – super calls are statically bound, in traits, they are dynamically bound. If
you write “super.toString” in a class, you know exactly which method
implementation will be invoked.

In Trait – When you write the same thing in a trait, the method implementation to invoke for the super call is undefined when you define the trait. Rather, the implementation to invoke will be determined anew each time the trait is mixed into a concrete class. This
allows traits to work as stackable modifications!!