I'm teaching myself scala and trying to fatten my FP skills.
One of my references, Essentials of Programming Languages (available here), has a handy list of easy recursive functions. On page page 27/50, we are asked to implement swapper() function.
(swapper s1 s2 slist) returns a list the same as slist, but with all occurrences of s1 replaced by s2 and all occurrences of s2 replaced by s1. > (swapper ’a ’d ’(a b c d)) (d b c a) > (swapper ’a ’d ’(a d () c d)) (d a () c a) > (swapper ’x ’y ’((x) y (z (x)))) ((y) x (z (y))) In scala, this is:
swapper("a", "d", List("a","b","c","d")) swapper("a", "d", List("a","d",List(),"c","d")) swapper("x", "y", List( List("x"), "y", List("z", List("x")))) My scala version handles all versions save the final x.
def swapper(a: Any, b: Any, lst: List[Any]): List[Any] ={ def r(subList :List[Any], acc : List[Any]): List[Any] ={ def swap (x :Any, xs: List[Any]) = if(x == a){ r(xs, acc :+ b) } else if (x == b) { r(xs, acc :+ a) } else { r(xs, acc :+ x) } subList match { case Nil => acc case List(x) :: xs => r(xs, r(List(x), List()) +: acc) case x :: xs => swap(x,xs) //case List(x) :: xs => } } r(lst, List()) } Instinctively, I think this is because I have no swap on the section "case List(x) :: xs" but I'm still struggling to fix it.
More difficult, still, this case breaks the tail-call optimization. How can I do this and where can I go to learn more about the general solution?