Scala by Example — Chapter 09
/**
* Exercise 9.1.1 Provide an implementation of the missing function insert.
*/
def isort(xs: List[Int]): List[Int] =
if (xs.isEmpty) Nil
else insert(xs.head, isort(xs.tail))
def insert(x: Int, xs: List[Int]): List[Int] = xs match {
case Nil => List(x)
case t :: ts =>
if (x < = t)
x :: xs
else
t :: insert(x, ts)
}
val testList = 9 :: 3 :: 10 :: 12 :: 1 :: 37 :: 2 :: 200 :: Nil
println("Original: " + testList)
println("Sorted: " + isort(testList))
/**
* Exercise 9.2.1 Design a tail-recursive version of length.
*/
def length(list: List[Int]): Int = {
def iter(l: List[Int], accumulator: Int): Int = l match {
case Nil => accumulator
case h :: t => iter(t, accumulator + 1)
}
iter(list, 0)
}
// test
val testList = 9 :: 3 :: 10 :: 12 :: 1 :: 37 :: 2 :: 200 :: Nil
println("Size of list: " + length(testList))
/**
* Exercise 9.4.1 Consider a function which squares all elements of a list
* and returns a list with the results. Complete the following two equivalent
* definitions of squareList.
*
* def squareList(xs: List[Int]): List[Int] = xs match {
* case List() => ??
* case y :: ys => ??
* }
*
* def squareList(xs: List[Int]): List[Int] = xs map ??
*/
def squareList(xs: List[Int]): List[Int] = xs match {
case List() => Nil
case y :: ys => (y * y) :: ys
}
def squareList(xs: List[Int]): List[Int] = xs map (x => x * x)
/**
* Exercise 9.4.2 Consider the problem of writing a function flatten, which
* takes a list of element lists as arguments. The result of flatten should be
* the concatenation of all element lists into a single list. Here is an
* implementation of this method in terms of :\.
*
* def flatten[A](xs: List[List[A]]): List[A] =
* (xs :\ (Nil: List[A])) {(x, xs) => x ::: xs}
*
* Consider replacing the body of flatten by
*
* ((Nil: List[A]) /: xs) ((xs, x) => xs ::: x)
*
* What would be the difference in asymptotic complexity between the two
* versions of flatten?
*
* In fact flatten is predefined together with a set of other userful function
* in an object called List in the standatd Scala library. It can be accessed
* from user program by calling List.flatten. Note that flatten is not a method
* of class List - it would not make sense there, since it applies only to
* lists of lists, not to all lists in general.
*/
/*
In fact, the use of {} vs () doesn't make sintatic or semantic difference.
In curry model of Scala, both the foldLeft /: and foldRight :\ methods
define the function as second curry parammeter. So, the version of function
that use /: can be writen like :\
*/
def flattenRight[A](xs: List[List[A]]): List[A] =
(xs :\ (Nil: List[A])) {(x, xs) => x ::: xs}
/*
Note that is the same function, just changing the application of flatten
function. So, there's no difference in asymptotic complexity between the
two implementation.
*/
/**
* Exercise 9.4.3 Fill in the missing expressions to complete the following
* definitions of some basic list-manipulation operations as fold operations.
*
* def mapFun[A, B](xs: List[A], f: A => B): List[B] =
* (xs :\ List[B]()){ ?? }
*
* def lengthFun[A](xs: List[A]): int =
* (0 /: xs){ ?? }
*/
def mapFun[A, B](xs: List[A], f: A => B): List[B] =
(xs :\ List[B]()){(x, fx) => f(x) :: xs}
def lengthFun[A](xs: List[A]): Int =
(0 /: xs){(acc, _) => acc + 1}