tags:

views:

93

answers:

2

How does foldRight[B](B) from scaladoc match the actual call foldRight(0)

args is an array of integers in string representation

val elems = args map Integer.parseInt
elems.foldRight(0) (_ + _)

Scaladoc says:

scala.Iterable.foldRight[B](B)((A, B) => B) : B
Combines the elements of this list together using the binary function f, from right to left, and starting with the value z. 

@note Will not terminate for infinite-sized collections. 

@return f(a0, f(a1, f(..., f(an, z)...))) if the list is [a0, a1, ..., an]. 

And not so imporant what do the periods after f(an, z) mean?

+5  A: 

Everything you need to know about foldLeft and foldRight can be gleaned from the following:

scala> List("1", "2", "3").foldRight("0"){(a, b) => "f(" + a + ", " + b + ")"}  
res21: java.lang.String = f(1, f(2, f(3, 0)))

scala> List("1", "2", "3").foldLeft("0"){(a, b) => "f(" + a + ", " + b + ")"} 
res22: java.lang.String = f(f(f(0, 1), 2), 3)
retronym
+5  A: 

As Steve said, the "..." are just ellipsis, indicating that a variable number of parameters that are not being shown.

Let's go to the Scaladoc, and show this step by step:

def foldRight[B](z: B)(op: (B, A) ⇒ B): B

That doesn't show enough. What is A? That is defined in the Iterable class (or whatever other class it is defined for):

trait Iterable[+A] extends AnyRef // Scala 2.7
trait Iterable[+A] extends Traversable[A] with GenericTraversableTemplate[A, Iterable[A][A]] with IterableLike[A, Iterable[A]] // scala 2.8

Ok, so A is the type of the collection. In your example, A would stand for Int:

val elems = args map Integer.parseInt

Next, [B]. That's a type parameter. Basically, the following two calls are identical in practice, but the first has the type parameter inferred by the compiler:

elems.foldRight(0) (_ + _)
elems.foldRight[Int](0) (_ + _)

If you used 0L instead of 0, then B would stand for Long instead. If you passed a "" instead of 0, then B would stand for String. You can try these out, they all will work.

So, B is Int and z is 0. Note that there are two sets parenthesis in the declaration. That means the function is curried. It receives two sets of parameters, beyond, as well as the type parameter ([B]). What that means is that you can ommit the second set of parameter, and that will return a function which takes that second set of parameter, and returns the expected result. For example:

val elemsFolder: ((Int, Int) => Int) => Int = elems.foldRight(0)

Which you could then call like this:

elemsFolder(_ + _)

Anyway, the second set receives op, which is expected to be of type (B, A) => B. Or, in other words, a function which receives two parameters -- the first being the same type as z, and the second being the same type as the type of the collection -- and returns a result of the same type as the first parameter. Since both A and B are Int, it will be a function of (Int, Int) => Int. If you passed "", then it would be a function of type (String, Int) => String.

Finally, the return type of the collection is B, which means whatever is the type of z, that will be the type returned by foldRight.

As for how foldRight works, it goes a bit like this:

def foldRight[B](z: B)(op: (B, A) => B): B = {
  var acc: B = z
  var it = this.reverse.elements // this.reverse.iterator on Scala 2.8
  while (!it.isEmpty) {
    acc = op(acc, it.next)
  }
  return acc
}

Which, I hope should be easy enough to understand.

Daniel
@Daniel thank you so much for this detailed explanation
stacker