Monday 23 September 2013

Simple Tuples for the Tired, Plus a Lesson in the Uniform Access Principle

I’m back on the early train again.  I’m tackling Tuples again too. (Atomic Scala, “Tuples” atom.)

I’m after the “Brevity” and “A Question of Style” atoms too, so the more succinct syntax coupled with something my Java-brain isn’t tuned into (plus, I would argue, the early hour) meant I did a quadruple-take and then a little investigation before Tuple unpacking made sense to me.  The reason?  This idiom (for I’m guessing it’s idiomatic:

def f = (1, 3.14, “Mouse”, false, “Altitude”)

What do we know from this, despite the spare syntax?

  1. it’s a function (because of the “def”)
  2. it’s called “f
  3. it takes no arguments, and does not mutate state (no parentheses just after the method name)
  4. it comprises a single expression (no curly braces)
  5. the return type is a tuple
  6. this return type is implicit inferred by the compiler (no need to specify in the method signature) (thanks Semeru-san)

With that in mind, what does this function do?  Well, nothing. It only serves to make and return a 5-value tuple which can be captured in a val or var; the first element of which is an Int, the second a Double, the third and fifth are Strings and the fourth is a Boolean.  In short, it’s a very simple tuple-builder.

Next step in the atom is to prove to ourselves that a tuple is just a collection of vals.  Firstly, we allocate our tuple to a val:

val (n, d, a, b, h) = f

That’s a little scary to the uninitiated (or tired) too. But it’s simply saying that I want to call the previously defined tuple-maker function, f, and then store the resulting tuple in another, explicitly defined, tuple of vals. This is called unpacking, and that then means, as well as a val for the tuple as a whole, we also have vals for each individual element and can manipulate them individually (notice the order change in the second line, and the “is” function comes from AtomicTest):

(n, d, a, b, h) is (1,3.14,"Mouse",false,"Altitude")
(a, b, n, d, h) is ("Mouse", false, 1, 3.14, "Altitude")

The final little chunk is some tuple indexing.  Again, this has an unfamiliar syntax, but makes sense once you roll it around a little:

f._1 is 1           // NOTE: NOT ZERO-INDEXED!
f._2 is 3.14
f._3 is "Mouse"
f._4 is false
f._5 is "Altitude"

This seemed a little haywire at first, but it makes perfect sense.  Again, breaking it down, we have f, the tuple-maker function from before, which returns a tuple of elements in a specific order when called.  So after the “f” we have a tuple.  We can then call methods on this (using the “.” in this example) and the methods we are calling here are the ones for indexing.

Lessons Learned

  1. Trying to learn a new type of language when still waking up is difficult
  2. There is a secret point that this atom is also making: In this simplest of simple functions, f, we seeing the uniform access principle in action. That is to say, as functions are first-class, I should be able to do with a function what I would do with any other object, and it should be transparent.  It was this transparency that pulled me up short.  Now, having realised this, I’m a lot more comfortable with the principle, and another small piece of Scala syntax

3 comments:

  1. One nit: your #6 above says the type is "implicit". You should probably avoid that terminology, as it is a different concept in Scala. Better terminology here is that the type is "inferred" (by the compiler).

    ReplyDelete