It's been a while since I've posted here, work and another side project (which resulted in a great trip to Italy :-) have kept me busy for the last little while. But I hope to continue making good progress through Seven Languages. So I will start with a modest update since the exercises for day 2 of scala weren't terribly long (just two questions). The main focus of this section was introducing some of scala's basic collections and a few of the more functional features in Scala like anonymous functions.
The code show a few simple operations being done on a list. We are using the foldLeft function to first find the number of elements in a list and then to count the number of characters in a list of strings. FoldLeft is a function that takes an initial value and a block of code it runs the block of code for each element in the collection being iterated over and on each subsequent iteration passes in the result of the code block on the previous iteration (on the first iteration the initial value is passed in). Or as the scala docs would say "Applies a binary operator to a start value and all elements of this immutable iterable collection, going left to right." In this way the we effectively can maintain an accumulator as we iterate through a collection, in this case we use it to store the count (or sum) of what we have seen so far.
The example shows two different syntax options for this function. The second is an operator with what to me is a more cryptic syntax (why exactly are the curly braces needed?), that I would likely mangle if writing from memory. I much prefer the first form, which has a somewhat interesting signature, which you will notice has a double set of parentheses; of the form f()(). This form uses Scala's support for currying or partially applied functions. Essentially the call to foldLeft(0) returns a function that we can then call again this time passing it the block of code we want it to execute ( (sum, word) => sum + 1 // defines an anonymous function ). The first function returned is a partial function, that is, not all of its arguments are currently bound. It is like taking a function that adds two numbers and breaking it down into a function that takes one number and returns a second function that can add another number to the number now in its definition.
The second exercise was to write some code tat would replace certain words in a string with other words. Not a lot to talk about here, though they how some of the other common iteration functions. I wrote a few different ways to get this done (though they are not robust with respect to what may be separating the words to be replaced), the most interesting of which may be the second one, which uses scala's pattern matching syntax to make the solution more elegant. This pattern matching offers a bit more than the standard switch/case constructs common to many programming languages, it is somewhat more powerful with respect to what it can match, as opposed to just the final value of an expression, it can match well, a pattern. This is hinted at somewhat in the Some(x) => x, we match against Some(x) and are able to use x. Looking around for other examples online, it reminds me a bit of unification in Prolog.
So what are these None and Some values? These represent scala's Option class, which is an approach that scala provides for dealing with nullable values (values that could potentially be null), without actually returning null, and thus avoiding NullPointerErrors. I had to deal with them because a Map[String, X] will return a value of type Option[X] when you try to get something from it, this represents that the key you used may not be in the map. When not present the value will be None and when present the value will be Some(x), we can call (a different) get on Some(x) to actually get x. I'm curious to see more examples of Option in use, None has a few methods (such as getOrElse) that supposedly make it easier/more elegant to deal with then null.
That is it for day 2! There is a bit more code there that shows doing file Io in scala.The exercises also gave me more of a chance to look around the scala docs. Which aren't always easy to decipher (or guess at where some particular functionality may lie).