I’ve got part of code from friend and I’m trying to understand it and write it in some other way. “gotowe” is a sorted list of ("2011-12-22",-600.00) elements
val wartosci = gotowe.foldLeft (List(initial_ballance)){
case ((h::t), x) => (x._2 + h)::h::t
case _ => Nil
}.reverse
That is quite okay but how with this usage of foldLeft? (I’ve put all extra necessary lines):
val max = wartosci.max
val min = wartosci.min
val wychylenie = if(math.abs(min)>max){math.abs(min)}else{max}
def scale(x: Double) =
(x / wychylenie) * 500
def point(x: Double) =
{val z:Int = (500 - x).toInt
z}
val (points, _) = wartosci.foldLeft(("", 1)){case ((a, i), h) => (a + " " + (i * 4) + "," + point(scale(h)), i + 1)}
when I print points I’ve got a list of values, and don’t know why not something like pairs of values
There are a couple of concepts at work here, which we’ll examine in turn to work out what’s going on:
Let’s first look at the definition of foldLeft:
So, in your example we’re taking a list of Tuple2[String, Float] (or something like that) and folding it into the value z, which in this case is a List containing one element,
initial_balance.Now, our
fin this case is the code inside the braces. It uses pattern matching to compose a partial function from the pair(b,a)– where in this casebis the ‘cumulative result’ andais the next item in the list. This is the crux of what a fold does – it collapses the list into a value, using specific rules governing how to add each element at a time.What is pattern matching / a partial function? Pattern matching is a very powerful technique for conditioning on and extracting things from input data. We give it something to look for – the
casepart of the expression – and tell it how to deal with it following the=>. The power of this is that thecaseexpression doesn’t just match, say, numbers or specific strings as might the switch statement in java, but can match, for example, Lists of a certain length, or email addresses, or specific tuples. Even more, you can use it to automatically get certain parts of the match – the domain of the email address, the third element of the list etc.We’ll look at the first pattern:
case ((h::t), x) => (x._2 + h)::h::tThe left hand side (before the
=>) is used to match the value we’re looking for and extract the specific pieces we care about. In this case, we’re looking for a tuple where the first element is a list consisting of a head (h) and a tail(t), and the second element is just the next element of the list. Theh::tis an extractor pattern – it’s matching the object ::(h,t) which constructs aListby prependinghonto an existingListt.When we’ve matched this, we follow the instructions to the right of the
=>to foldxinto the cumulative value. To do this, we take the right hand side of the date/value tuple (the._2), add it to the last value in the list (the head), and then push itself on to the head of the list. You’ll notice this is using the same syntax as we used in the pattern match – using::to prepend elements to aList.The effect in this case is to create a running total of what’s going on.
The second case doesn’t really do much – it’s a catch all case, but as this is being used in a fold it should never get called – we’re always going to return something that looks like
((h::t), x).Finally, we reverse the whole thing! So what we’re left with is a list of balances after each transaction, running from oldest to youngest.