## Tuesday, September 22, 2009

### UnfoldLeft and Right

Todays topic does not introduce anything new, it just a useful example of using a function to create a list of objects. This is NOT part of the standard library.

The methods are called unfoldRight and unfoldLeft because they are more or less the inverse of foldLeft and foldRight. foldLeft and Right run a function on each element in a list producing some result. unfoldLeft and right produce a list from a function and a seed value. The List is created from executing the function repeatedly with the result from the previous execution (or the seed value). Each function call returns a result which is the element in the list. The list is done when the function returns None rather than Some(x).

This sample is directly derived from the samples: http://paste.pocoo.org/show/140865/

Remember the performance differences between the two. Adding an element to the head of scala list is a constant operation but adding an element to the end(tail) of the list is linear time based on the size of the list. So unfoldLeft will typically suffer from worse performance.
`scala> def unfoldRight[A, B](seed: B)(f: B => Option[(A, B)]): List[A] = f(seed) match {     |   case Some((a, b)) => a :: unfoldRight(b)(f)     |   case None => Nil     | }unfoldRight: [A,B](B)((B) => Option[(A, B)])List[A]scala> unfoldRight(10) { x => if (x == 0) None else Some((x, x - 1)) }res0: List[Int] = List(10, 9, 8, 7, 6, 5, 4, 3, 2, 1)scala> unfoldRight("Jesse") { x => if (x.length == 0) None else Some((x, x.drop(1).toString)) }res2: List[java.lang.String] = List(Jesse, esse, sse, se, e)scala> def unfoldLeft[A, B](seed: B)(f: B => Option[(B, A)]) = {     |   def loop(seed: B)(ls: List[A]): List[A] = f(seed) match {     |     case Some((b, a)) => loop(b)(a :: ls)     |     case None => ls     |   }     |     |   loop(seed)(Nil)     | }unfoldLeft: [A,B](B)((B) => Option[(B, A)])List[A]scala> unfoldLeft(1) { x => if (x == 11) None else Some((x + 1, x)) }res0: List[Int] = List(10, 9, 8, 7, 6, 5, 4, 3, 2, 1)// Notice that the result is ordered in the opposite way from unfoldRight// Also notice the order of the list is reversed since the algorithm is the same but// unfoldLeft adds to end of list.scala> unfoldLeft("Jesse")  { x => if (x.length == 0) None else Some((x.drop(1).toString,x)) }res1: List[java.lang.String] = List(e, se, sse, esse, Jesse)`