Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is scala list class named ::

Tags:

list

scala

Why is the scala list implementation named :: and not a class name? Is there some special meaning behind that?

like image 564
Jeff Storey Avatar asked Oct 06 '11 04:10

Jeff Storey


People also ask

How do you define a list in Scala?

Syntax for defining a Scala List. val variable_name: List[type] = List(item1, item2, item3) or val variable_name = List(item1, item2, item3) A list in Scala is mostly like a Scala array. However, the Scala List is immutable and represents a linked list data structure. On the other hand, Scala array is flat and mutable.

What is Xs in Scala?

Basically it's a naming convention that originated in LISP. The rationale behind it is that: X is a common placeholder name. XS is pronounced X'es, i.e "many X".

Is list immutable in Scala?

A list is a collection which contains immutable data.

Does list maintain insertion order Scala?

In scala, ListSet class implements immutable sets using a list-based data structure. Elements are stored in reversed insertion order, That means the newest element is at the head of the list. It maintains insertion order. Listset is used only for a small number of elements.


2 Answers

A linked list is composed of two cases: a cons cell (with a head and a tail), and the empty list. These cases are called :: and Nil respectively in Scala, as in other languages with ML heritage. In an immutable implementation, the most natural encoding looks something like this:

sealed trait List[+A]

case class Cons[+A](head: A, tail: List[A]) extends List[A]
case object Nil extends List[Nothing]

This works just fine and there's really nothing wrong with it. You can define a :: method on List (or prepend, if you prefer), and things work exactly as you would expect. In this case, the "concrete implementation" of List will be Cons, though technically both Cons and Nil are concrete implementations.

Here's the problem though: we want to be able to pattern-match on an instance of List to get back the contents. As things stand, that pattern matching would require the following syntax:

def sum(xs: List[Int]): Int = xs match {
  case Cons(hd, tl) => hd + sum(tl)
  case Nil => 0
}

This is a bit ugly though. What we really want is to be able to use the :: operator in our pattern matching just the same as we use it when constructing the list originally. This is why the Cons class is named ::.

By defining a case class of two parameters, we're basically telling Scala that we want it to allow us to use that case class as an infix extractor in pattern matching. The trailing colon makes that extractor right-associative, giving us the expected syntax:

sealed trait List[+A]

case class ::[+A](head: A, tail: List[A]) extends List[A]
case object Nil extends List[Nothing]

def sum(xs: List[Int]): Int = xs match {
  case hd :: tl => hd + sum(tl)
  case Nil => 0
}

This is why any instance of List that has contents will be an instance of class ::, since that is the non-empty implementation of List.

like image 107
Daniel Spiewak Avatar answered Sep 30 '22 02:09

Daniel Spiewak


This is to work with pattern matching. You have something called an Infix Operator Patterns where pattern p op q is equivalent to the constructor or extractor pattern op(p, q).

So the case class :: defines the constructor ::(head, tail). That allows you to match like this:

list match {
  case ::(head, tail) =>
}

But with the infix operator pattern, you can write the more familiar syntax:

list match {
  case head :: tail =>
}

Note that a stackoverflow search on "[scala] infix operator pattern" returns similar questions and additional use cases of the pattern.

like image 39
huynhjl Avatar answered Sep 30 '22 02:09

huynhjl