Friday, 17 January 2014

Classes in Scala - Beyond the (Java) Expected

There is a lot more power to the Scala type system than any other language I know, and I’ve yet to come across - let along understand – most of it. (I’ve tried a few times now to compose a post on this topic, but realised each time I was still way off being in a position to do so.) However, in my latest reading of Scala for the Impatient, I’ve come across some interesting extensions to what I learned from Atomic Scala.

Object-Private Fields

As you’d expect (if you’re coming from Java as I have) methods in a (Scala) class can access private fields of all objects which are derived from that class. But you can also add a more restrictive access flag so that objects can only access private fields of the current object:

private[this] var name // access someObject.name is not allowed

example from Scala for the Impatient by Cay Horstmann, pp51

Behind the scenes (which I’m beginning to realise is a good way to grok these things) class-private fields have private getters and setters generated for them, whereas object-private fields have neither getters or setters.

You can, if you like, even go one step further, replacing “private[this]” with “private[className]". In this case, the field can be accessed only by methods of the named class.  Here, the generated code has to generate public getters and setters because the JVM doesn’t support this fine grained level of access control.

Bean Properties

A simple one this. Scala by default creates getters which are simply the same name as the field, and setters which are the name of the field plus “_”.  This doesn’t meet the JavaBeans spec, so to also get the expected getFieldName and setFieldName methods you can:

class Person {
    @BeanProperty var name : String = _
}

example from Scala for the Impatient by Cay Horstmann, pp52

Primary Constructor Parameters

These can use @BeanProperty, private[this] and private[className] forms on top of the “expected” ones.

Additionally, if you declare a Primary Class Constructor Parameter without a val or a var form, then how the parameter is processed is dependent upon how you use the field inside the class. In the following, immutable fields name and age are declared and initialised that are object-private:

class Person(name: String, age: Int) {
    def description = name + " is " + age + " years old"
}

example from Scala for the Impatient by Cay Horstmann, pp55

However, if no method uses the parameters they are not saved as fields at all, and they are instead simply treated as parameters that can be accessed within the Primary Constructor and no more.

As suggested by Martin Odersky and helpfully repeated by Cay, I found it useful to think of Scala classes as being able to take parameters just like methods do.  That makes perfect sense to me.

Before we move on, a final word on making a Primary Constructor private:

class Person private(val id: Int) { ... }

example from Scala for the Impatient by Cay Horstmann, pp57

Lovely for enforcing builders etc, and also just like in Java.  Bosh!

Nested Classes

In our final topic, again, Scala seems hyper-flexible.  Anything (pretty much) can go inside anything else (functions within functions for examples) and it’s no surprise to find out that classes can go within other classes.  I won’t lift the whole example from Cay’s book here (it’s in the free section, go and look at the bottom of page 57) but the important thing to note is that instances have their own classes, just like instances have their own fields too.  That is to say, two nested classes of two different instances of the containing class, are two different classes.

It sounds a little counter intuitive at first, but once you have a play with it it makes more and more sense.  However, if you do want to have things as you’d expect from a Java perspective, you can always stick the nested class definition in the companion object (which, you’ll recall is shared across all instances of a class).  Or (and this pushed me out of my comfort-zone significantly, you can use a type projection, but I’ll not go into that here. I get the impression that once I get to things like that then I’ll really be moving towards the domain of advanced Scala consumer.

Wednesday, 8 January 2014

Weighing filter & map Against for’s guards and yield

On the surface, it seems that a combination of filter and map can achieve the same end as a for-comprehension with judicious use of guards (e.g. if-expressions) and yield.  Or to say the same thing in code:

b.filter(_ % 2 == 0).map(2 * _)

takes the same inputs and produces the same outputs (with the same lack of side effects) as:

for (elem <- b if (b % 2 == 0)) yield 2 * elem

Cay Horstmann (for it is from his book, Scala for the Impatient that this code and the jumping-off point for this post is taken) points out that the former is preferred by those more experienced or comfortable with the functional idiom, but what I want to examine for a little while is if there are any other reasons why you would pick one over the other.

Legibility

Lets kick off with my old drum, and consider how clean and clear to the eye and comprehending mind they both are.  If I’m being honest, in the example above, the filter/map combo has it hands down.  Just as the method calls chain, so does your understanding as you follow it through, from left to right.  With the for on the other hand, you need to either ignore the elem <- b, jump to the guard to get an image of what elem is, before jumping back to the right again to the yield.  A lot of work for such a simple piece of logic.

It also helps greatly that (now I have a good mental construct for map) that we can read the method names and immediately call to mind what is happening.  In the for version there are no such explicit semantic clues to latch onto.

Flexibility

So far it’s a resounding 1-0 in favour of filter and map, but lets redress the balance.  The example we’ve used so far is an incredibly simple one. What if we needed to have two generators?

for (i <- 1 to 3; j <- 1 to 3) ...

Simple. However our filter and map combo can’t compete because here we’re calling methods which need to be on single object instances.  There is nothing available to us which can produce the same effect as simply (I’m sure you could get all complicated, but there’s nothing which will have the “just what I expected” feel of this common for element.

Before we move on, we out to kick it up another notch and mention yield expressions can get pretty powerful too (note this example was lazily and brazenly stolen from Atomic Scala by Bruce Eckel and Dianne Marsh):

def yielding3(v:Vector[Int]) : Vector[Int] = {
  for {
    n <- v
    if n < 10
    isOdd = (n % 2 != 0)
    if(isOdd)
  } yield {
    val u = n * 10
    u + 2
  }
}

Here, while it is conceivable that in some circumstances our filter and map combo could achieve something similar, it would likely be at the expense of their legibility (which is worth a lot to my mind).

Before we finish this aspect, it’s worth pointing out that for’s multiple guards could be represented easily by chaining the same number of filter calls instead of the single one shown at the top of this post, but that’s not quite enough to tip this one back towards a no-score-draw.

Summary

So, it seems that there are indeed reasons when you would want to use for in preference to filter and map. In all cases it’s when you want to unleash a bit of the generator / yield power beyond the simple simple use case.  Seems pretty sensible to me, and a rule-of-thumb I’ll be applying in the future.

Functions and Methods – A Subtle Distinction

There are a great many benefits to be learning something like Scala, when you have an educational background like I do.  Even small snippets of text can flesh out whole expanses of a conceptual landscape, and not just a Scala-one.

Today it is the following lines from Cay Horstmann’s Scala for the Impatient:

“Scala has functions in addition to methods. A method operates on an object, but a function doesn’t. C++ has functions as well, but in Java you imitate them with static methods”

from Scala for the Impatient by Cay Horstmann, pp 21

I’ve been here before, but in the mass of words I copied from Wikipedia at that point, this simple distinction was lost on me (it’s there, but implicitly). It’s an important distinction too – a method has an object, a function doesn’t - and another fine conceptual tool which, added to my armoury of subtle distinctions and concepts, should help me get further under the skin of both Scala and other languages.

Tuesday, 7 January 2014

Back on the Old for-Comprehensions Again – Filters and Guard Conditions

NOTE: There's an update to this post, based on a Google+ comment from Chris Phelps.  Cheers Chris!
I’m back on Scala’s for comprehension construct, courtesy of chapter 2 of Cay Horstmann’sScala for the Impatient”.  As you’d expect from a book with such a title, he wastes no time in getting to the point, and after a quick (thou comprehensive) intro to the basic single-generator-and-little-else flavour he’s off into multiple generators:
for (i <- 1 to 3; j <- 1 to 3)
    print((10 * i + j) + " ") // Prints 11 12 13 21 22 23 31 32 33

from Scala for the Impatient, by Cay Horstmann, pp 20
The generators here are in the first set of parens, and give us the i and j variables which are then used in the body of the loop. All very clear. 
Then we’re onto the addition of guard conditions:
for (i <- 1 to 3; j <- 1 to 3 if i != j)    print((10 * i + j) + " ") // Prints 12 13 21 23 31 32
from Scala for the Impatient, by Cay Horstmann, pp20
Now before we had “filters” which seemed to do a similar thing – only continue evaluation of that iteration of the loop if they evaluated to true themselves - but filters were applied in the body whereas here the guard condition is found within the generator parens, at least in this example.
A bit of reading ahead soon reveals that these “filters” and “guard conditions” seem to be the same thing, but things just looked different because there are two valid forms of the for-comprehension syntax – one with parens and semi-colons (Cay’s way in) and the other with curly braces (the Atomic Scala opener).  But before we make any sweeping statements, lets check to make sure.  Here’s what happens when we start with a parens-version and convert it to the curly-braces flavour:
for (i <- 1 to 3; from = 4 - i; j <- from to 3)
  print((10 * i + j) + " ")
// Prints 13 22 23 31 32 33

for {             // added a newline and replaced the open-paren with a curly brace
  i <- 1 to 3     // added a newline and dropped the semicolon
  from = 4 – i    // added a newline and dropped the semicolon
  j <- from to 3  // added a newline and dropped the semicolon
}                 // added a newline and replaced the close-paren with a curly brace
print((10 * i + j) + " ")
// Still prints 13 22 23 31 32 33

adapted from Scala for the Impatient, by Cay Horstmann, pp20
As expected, they are the same.  I’m not sure if that added flexibility makes me happy or sad.  I can however cope with the different ways of referring to filters/guard-conditions. But wait, there’s no time for emotion, yield is about to be introduced.
And here again another subtlety I wasn’t previously aware of seems to have arisen – without a yield, what we have is called a “for-loop”, but once we’re yielding it’s a “for-comprehension”.  However, as I am already aware, yielding creates a collection filled with objects of the type output by the first generator, so it’s swings and roundabouts.
Update (08/02/2014): Chris Phelps (one of my Scala-mentors, for which I'm exceedingly grateful) comments: "Underneath the syntactic sugar, the "filter" or "guard" actually uses a variant of the filter method (withFilter), so if you thought those filters were related to the filter method, well spotted."  Looks like I'm on the right track.