0

I might sound silly but I am new to scala so please bear with me. I am little confused about using switch case in scala. As per the example of finding the last element of a list

what is the letter 'h' and 'k' is doing ? In short if somebody can explain the below, I will be very grateful.

def recLast[A](ls: List[A]): A = ls match {
    case h :: Nil => h
    case b :: rest => recLast(rest)
}
1
  • match ... case is used in pattern matching. Here we are reasoning over a linked list - in the first case we look for a match on the last element of the list. The second case removes the head and recurses on the tail. Essentially the function finds the last element in the list by walking it Commented Apr 2, 2017 at 6:17

2 Answers 2

2

In Scala, a List[A] is an abstract class implemented using singly linked list, composed of a head element of type A, and a tail of type List[A]. The concrete implementations are Cons (::), which represents which has a head and a tail, and Nil which is the empty list.

What happens in recLast is that the List[A] is decomposed using a feature called Pattern Matching. The case denotes a pattern which we attempt to match on.

The first case:

case h :: Nil => h

Means "In case the List[A] contains a head element h and a tail which is the empty list (called Nil), then return the head element.

The second case

case b :: rest => recLast(rest)

Means "In case the List[A] contains a head element which we bind to b and a tail which we bind to rest, take the tail of the list and recursively call recLast with it.

One way of pattern matching on a List[A] is using the Cons class. By doing head :: tail, which call the ::.apply method in infix notation, it is equivalent to: ::.apply(head, tail)

Appendix

The concrete implementation of the classes:

:: (Cons):

final case class ::[B](override val head: B, 
                       private[scala] var tl: List[B]) extends List[B] {
  override def tail : List[B] = tl
  override def isEmpty: Boolean = false
}

Nil:

case object Nil extends List[Nothing] {
  override def isEmpty = true
  override def head: Nothing =
    throw new NoSuchElementException("head of empty list")
  override def tail: List[Nothing] =
    throw new UnsupportedOperationException("tail of empty list")
  override def equals(that: Any) = that match {
    case that1: scala.collection.GenSeq[_] => that1.isEmpty
    case _ => false
  }
}
Sign up to request clarification or add additional context in comments.

Comments

0

the case statement does pattern matching if the list has one element (i.e. it is :: Nil it would be matched for the first case and would be assigned to h the latter case does the same thing and also assigned the rest (tail) to "rest"

you can also see this pattern matching if you write the following in the REPL

scala> val h :: rest = List(1,2,3,4)
h: Int = 1
rest: List[Int] = List(2, 3, 4)

Comments