-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathfunctionsOnLists.sc
83 lines (67 loc) · 2.07 KB
/
functionsOnLists.sc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
/*
* data List[A] = Nil | A :: List[A]
*
* In the context of the org chart example, we already saw uses of the
* Seq.map and Seq.fold/sum functions.
*
* - map applies a function to each item in a list
*
* - foldLeft successively applies a function to the partial result
* accumulated so far and the next list item
*
* - There is also foldRight, which does the same thing but starting
* from the back of the list. This makes a difference unless the function
* is commutative (which also implies that both of its arguments are of
* the same type).
* When used with lists, foldRight usually does things in the right order
* but is not tail-recursive, so its recursive call stack might grow very
* large.
*
* - filter keeps only those items that satisfy the given predicate
* (boolean function).
*/
assert { 1 :: 2 :: 3 :: Nil == List(1, 2, 3) }
def reverse[A]: List[A] => List[A] = {
case Nil => Nil
case h :: t => reverse(t) :+ h
}
/** DRY */
def test(rev: List[Int] => List[Int]) = {
assert { rev(Nil) == Nil }
assert { rev((1 to 5).toList) == (5 to 1 by -1).toList }
}
test { reverse }
def reverseAsFoldLeft[A](xs: List[A]) =
xs.foldLeft(Nil: List[A]) {
(r, x) => x :: r // same as +:
}
test { reverseAsFoldLeft }
def reverseAsFoldRight[A](xs: List[A]) =
xs.foldRight(Nil: List[A]) {
(x, r) => r :+ x // mirror image of +:
}
test { reverseAsFoldRight }
/** Because it is tail-recursive, this version of `reverse` runs in constant space. */
@scala.annotation.tailrec
def reverseAcc[A](xs: List[A], acc: List[A] = Nil): List[A] = xs match {
case Nil => acc
case h :: t => reverseAcc(t, h :: acc)
}
test { reverseAcc(_) }
def reverseWhile[A](xs: List[A]): List[A] = {
var acc = List.empty[A]
var curr = xs
while (curr != Nil) {
acc = curr.head :: acc // same as acc ::= curr.head
curr = curr.tail
}
acc
}
test { reverseWhile }
// Up for a challenge? Try implementing these functions yourself and test
// if they behave like the predefined ones!
// TODO map
// TODO mapAsFold
// TODO foldLeft
// TODO append
println("■")