I know that the map function takes each element of a list (a sequence) and applies a function to it. Recursively (and without respect to termination conditions, etc)
map(s, f) = f(s.head) :: map(s.tail, f)
I am looking for a function that does something like
foo(s, f) = f(s) :: map(s.tail, f).
So a 'mapper' where the mapping function gets called on sublists and not individual elements. In lisp terms, I'm looking for a maplist, as opposed to a mapcar. Does something like this exist, or do I have to roll my own (or use recursion)?
Alternatively, I'd take a function that takes as input a sequence and returns a sequence of mid-to-end subsequences, ie
bar(s, f) = s :: bar(s.tail, f)
/* This approach defines mapList in terms of another useful method called tails. Like Daniel, I'll put it in an implicit extension to List, but that's purely a matter of taste */
implicit def richerList[A](list : List[A]) = new {
/* Here's a method called tails which returns each possible tail in the list. It is tail recursive so it won't blow up on large lists. Note that it differs slightly from a Haskell function of the same name. The Haskell version always adds an empty list on to the result */
def tails : List[List[A]] = {
def loop(ls : List[A], accum : List[List[A]]) : List[List[A]] = ls match {
case _ :: tail => loop(tail, ls :: accum)
case _ => accum
}
loop(list, Nil).reverse
}
/* This is what using tails looks like
scala> "abc".toList.tails
res0: List[List[Char]] = List(List(a, b, c), List(b, c), List(c))
*/
/* Now we can define mapList based on tails */
def mapList[B](f : List[A] => B) = tails map f
}
/* And this is what using mapList looks like
scala> "abc".toList mapList (_.reverse.mkString)
res1: List[String] = List(cba, cb, c)
*/
You've basically defined what you're looking for in pseudocode - so it's easy to add such a method to a Scala list using implicit conversions:
object ExtendedList{
implicit def List2ExtendedList[A](l:List[A])=new ExtendedList(l)
}
class ExtendedList[A](l:List[A]){
import ExtendedList._
def mapList[B](f:List[A]=>B):List[B]=l.length match {
case 0 => List()
case _ => f(l)::l.tail.mapList(f)
}
}
object Test extends Application{
import ExtendedList._
val test = List(5,4,3,2,1)
assert(List(15,10,6,3,1)==test.mapList{l=>(0/:l){_+_}})
}
Is this what you're looking for?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With