Wednesday, 8 January 2014

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.

Friday, 13 December 2013

Conceptualising map and flatMap

This time, we’re got a specially selected guest post from Chris at CodingFrog.  He’s way further down the Scala-learning path than I am, but that just means this post contains maximal goodness and he’s very kindly offered to share it with us. It certainly furthered my understanding in many areas, and made me want to look more into monads.  Take it away sir…

In this guest post, I wanted to address a few thoughts about map and flatMap. A number of types in the standard Scala libraries (so-called "monads", though there's a little more to monads than this - but this is not a monad post) have these helpful methods. Both map and flatMap are higher-order functions, meaning they take functions as arguments and apply these to the type's contents.

The first exposure most developers have to the map operation is in the context of a collection type. The map operation on a collection applies a mapping function to all the contents of the collection. Given a collection, for example a list, and a function, the function is applied to each element in the collection and a new collection made up of the results is returned. The mapping function takes a single argument, of the same type (or a supertype) of the collection contents, and returns a result, potentially of another type:

scala> def myFun(x: Int) = x * x

myFun: (x: Int)Int

scala> List(1,2,3) map { myFun }

res0: List[Int] = List(1, 4, 9)

This example shows a named function being passed to map, but of course a lambda could be used as well:

scala> List(1,2,3) map { x => x * x }

res1: List[Int] = List(1, 4, 9)

We can also use the '_' placeholder, though I personally like to be slightly more explicit with my lambdas to maintain readability. Note that I am also using infix notation for map and flatMap in all these examples, but the dotted calling style is perfectly valid as well.

Before going further, I'd like to comment on the naming of map and the relationship between the operation and the data type which shares this name. These two uses of “map” are slightly different, but there is a connection. First, the Map data type, as you likely know, is a type which contains key-value pairs. If you think about this slightly differently, this is a conceptual function which "maps" a relationship - given a key input, it produces a value output. The map operation applies a mapping function to values in a collection. You could even pass a Map data type to a map function to convert a collection of keys into a collection of values!:

scala> val myMap = Map(1 -> 1, 2->4, 3->9)

myMap: scala.collection.immutable.Map[Int,Int] = Map(1 -> 1, 2 -> 4, 3 -> 9)

scala> List(1,2,3) map { myMap }

res2: List[Int] = List(1, 4, 9)

Like map, the first exposure to flatMap is usually in a collection context. Suppose instead of a squaring function that returns a single value, you have a mapping function that returns a list from a given input:

scala> List(1,2,3) map { x => for {

     | y <- 1 to x toList

     | } yield y

     | }

res3: List[List[Int]] = List(List(1), List(1, 2), List(1, 2, 3))

In this case, instead of a simple list List[Int], we got a nested list List[List[Int]]! This may be what we want, but suppose we wanted to have a simple list. We can "flatten" this nested list, to remove a level of wrapping and give us a single list. flatMap does that for us in one step. So far so good:

scala> List(1,2,3) flatMap { x => for {

     | y <- 1 to x toList

     | } yield y

     | }

res4: List[Int] = List(1, 1, 2, 1, 2, 3)

So thinking about collections, it seems like we will be using the map operation much more frequently than we use the flatMap operation. After all, we are much more likely to use a function which gives us a single output for an input rather than one that creates nested collections. Again, we will have cases where we DO want that, but they are less common than the straightforward case.

But this isn't the case for other monad types. Let's look at the type Try. The Try type is a type which represents an operation that can fail. Try has two values - Success(t) which contains a successful result t; and Failure(ex) which contains an exception. In other words, instead of throwing the exception, we've grabbed it and stuffed it in a box. You don't know until you look in the box whether it contains the Success or the Failure (and you haven't jumped up the call stack to a catch clause). You can find out what is in the box with pattern matching:

scala> def examine(myTry: Try[Int]): Int = {

     | myTry match {

     | case Success(t) => t

     | case Failure(e) => -1

     | }

     | }

examine: (myTry: scala.util.Try[Int])Int

This is where I started to struggle to adapt my intuition of List map and flatMap, to the Try ideas of map and flatMap. So what would these mean? Map takes a function which takes a value (of type T) and converts it to another value (of type U, which may or may not be the same as type T). Now map on Try has a specific behaviour guarantee: for Success values, it will call the function on the value in the Success, and wrap the result back up in a Try.:

case Success(t) => Try(f(t))

For a Failure, it just returns this - in other words, it skips calling the function, and just returns the original failure:

case Failure(e) => this

But what if our mapping function wants to be able to represent failures? It's not hard to imagine wanting to have a sequence of operations, each of which could throw some exception. The chain will return a value if all operations in the sequence are successful, or else return the first failure. We can do this by using map. In this case, calling map on the first Try, will call the mapping function, which itself returns a Try value, and wrap that in a Try value:

scala> import scala.util.{Try, Success, Failure}

import scala.util.{Try, Success, Failure}


scala> def dangerOp1(i: Int): Try[Int] = {

     | if (i != 0) Success(i)

     | else Failure(new IllegalArgumentException)

     | }

dangerOp1: (i: Int)scala.util.Try[Int]


scala> val myTry = Success(5)

myTry: scala.util.Success[Int] = Success(5)


scala> myTry map { dangerOp1 }

res5: scala.util.Try[scala.util.Try[Int]] = Success(Success(5))


scala> val myTry2 = Failure(new NoSuchElementException)

myTry2: scala.util.Failure[Nothing] = Failure(java.util.NoSuchElementException)


scala> myTry2 map { dangerOp1 }

res6: scala.util.Try[scala.util.Try[Int]] = Failure(java.util.NoSuchElementException)

So we've gone from Try[T] to Try[Try[T]], just because we wanted to be able to have our mapping function return some exception cases. This could easily get out of hand if we want to keep mapping more and more functions which could return exceptional cases with Try! What can we do?

If we look back at our List example, we see that this is really the same case as when our mapping function itself returned a List. There we went from List[T] to List[List[T]], while here we're going from Try[T] to Try[Try[T]]. Our solution here is the same as it was there: we need to flatten a layer of nesting. We could take our first result, map our function, and then flatten the result, or we could do the map and the flatten in one step:

scala> myTry flatMap { dangerOp1 }

res7: scala.util.Try[Int] = Success(5)


scala> myTry2 flatMap { dangerOp1 }

res8: scala.util.Try[Int] = Failure(java.util.NoSuchElementException)

Learning map on List gave us this good (or at least, better) intuition for what mapping a higher order function onto that List means. But this didn't give us quite a rich enough intuition of what flatMap means. Applying functions that create lists to members of a list is just not a common enough pattern to really feel it in our bones. Other types, though, will give us the nested construction as our default pattern. It's quite easy, maybe even expected, to run a sequence of steps that each produce exceptions wrapped in Try. A sequence of operations where each one may return an error value wrapped in the Option monad seems pretty likely. When we step up to doing asynchronous coding, we can easily envision combining a sequence of operations that will complete in the future, hooking each up to be run in sequence whenever the previous step completes, by using the Future monad. In all these cases, flatMap is a much more natural and basic operation than map, which would keep wrapping each step in another level of nesting. By studying map and flatMap in terms of these types, we can get a better intuitve feel for how these operations combine values of these types, rather than falling back to our List intuition of these operations.

All of this has nice implications for for-comprehensions, which rely heavily on flatMap internally. But let's leave that for further study, and maybe another post.

Even More Legibility Wins (and no Losses) (Part 3 in a Occasional Series): Special “Option” Edition

I posted twice before about some of the things in Scala which I think help and hinder legibility – all from my personal perspective of course.  Well, here’s the third instalment.  It’s dedicated to the Option.  #winning:

Wins

  • Option types
    • just the concept in general – I think it’ll be a long time before I fully grok how great these really are
    • not to mention they’re biased (c.f. Atomic Scala, Atom: “Handling Non-Values with Option”, pp 352)
    • but also their being handled seamlessly in for comprehensions
    • as well as their having foreach and map functions on them
    • and the Option names: Some and None
  • null (even from Java code) being wrapped as a None

Losses

  • None – not that I can think of anyway…

Undecided

  • The name “Option” – Bruce and Dianne aren’t convinced. I don’t hate it. (c.f. Atomic Scala, Atom: “Handling Non-Values with Option”, pp 355)

Post-script

Excitingly, the same idiomatic concept makes it into the Scala equivalent of Java’s try/catch: Try(…) which produces either a Success or a Failure.  Far more on that to come in the next post (and much more), this time from a special guest: Colorado-resident, CodingFrog.

Wednesday, 20 November 2013

(Many) Legibility Wins and (a few) Losses (Part 2 in an Occasional Series)

I posted before about some of the things in Scala which I think help and hinder legibility – all from my personal perspective of course.  We’ll here’s the next instalment:

Wins

  • yield
  • Any” type, and its immediate syb-types
  • Pattern matching with types
  • Pattern matching with tuples
  • rockets (<= and =>) – so far at least…
  • (new Duck).myMethod – to keep the scope of the Duck instance as tight as possible
  • traits – I’ve always liked mixins anyway, but nothing is broken from what I liked in Ruby
  • the terse syntax (sans curly braces etc.) for defining classes when you don’t need it – e.g. “class MyClass
  • val c = new MyObject with MyTrait – when you don’t need to reuse the class definition elsewhere
  • sealed – does what it says on the tin
  • zip – ditto
  • take – ditto
  • + – adding a new key-value pair to an existing map. Gives you a new map back
  • catches and pattern matching
  • try blocks being expressions
  • exceptions being only for exceptional circumstances – a nice idiom

Losses

  • explicit setter definition (_=) - :$
  • set unions with ‘|
  • set differences with ‘&~’ or ‘--

Undecided

  • no parens for methods which have no side effects – sometimes, when these are abstract, they make you double-take a little

Overall, things are getting less and less surprising and more and more #winning.  Perhaps my resistance is being worn down. Perhaps I’m just more open to the experience.  Or perhaps all this is taking hold. One thing I do know however is that some of the method names on the collections classes are just plain wrong, but I don’t think I’m alone in thinking that.

Wednesday, 13 November 2013

Scala’s Type System – A Mid-Learning Checkpoint

Update (21st January, 2014): There is a subtle error in the section on “Enumerations (by extending Enumeration)”.  It’s fixed now.

WARNING: THIS POST CONTAINS WAY MORE QUESTIONS THAN ANSWERS

ALSO, APOLOGIES IF THE SCOPE OF THIS POST RIDES ROUGH-SHOD OVER THE CANONICAL DEFINITION OF A “TYPE-SYSTEM”.  IT SIMPLY CONTAINS EVERYTHING I BRING TO MIND WHEN I THINK ABOUT TYPES IN SCALA OR ANY LANGUAGE.  PLEASE FEEL FREE TO POINT OUT MY IDIOSYNCRACIES IN THE COMMENTS

You hear statements like “the best thing about Scala is it’s type system” and “Scala has a powerful type system" being flung around a lot.  For a long time, it’s been my aim to get a deep enough understanding of this aspect, as the people making this statement (in various forms) are people I respect a great deal.

I’ve made some brief forays into this territory before. Option Types is something I’ve heard Dick Wall talk about (and also something I think I understand despite not having covered it in my reading yet; thanks Dick) and the Fast Track to Scala course introduced me to the core class hierarchy (which seemed infinitely sensible – anything which includes “Any” as a type is clearly trying to strive for something I can relate to).  But these and other small aspects I’ve come across haven’t yet enabled me to honestly say I could defend the title of this post.

However, this isn’t to say I doubt I will get to this point eventually.  Just not yet.

To this end, I’ve just been went back over what I’ve learned so far about the type system.  It boils down to a set of facts. Lets begin with the ones which shouldn’t be surprising at all to a Java developer, plus a few little bits (signposted with italics) which might raise an eyebrow or produce a smile:

  • Classes and Objects – instantiate a class to create an object instance. Classes have fields and operations/methods
  • Creating Classes – class bodies are executed when the classes are created
  • Methods inside classes – methods have special access to other class elements (other methods and fields)
  • Fields – Always objects. Can be vals (immutable) or vars (mutable), or functions
  • Class Arguments – like constructors, but a list placed after the class name. Add a val/var to each definition to encapsulate it. You can have varargs too (but remember to put the definition last in the argument list)
  • Named and Default Arguments – you can specify the names of, and defaults for, Class arguments. If all args have defaults you can call “new *” without using any parentheses
  • Overloading – methods can be overloaded, as long as the argument lists differ (i.e. the signatures)
  • Constructors – automatically generated for us if we do nothing.  The expressions they contain are treated as statements, that is considered purely for their side effects. The result of the final expression is ignored, and the constructed object is returned instead. You can't use return half way through a set of constructor expressions either
  • Auxiliary Constructors – constructor overloading is possible, by defining a method called “this”. All must first call the Primary constructor (which is the constructor produced by the class argument list together with the class body) again using “this”. This means that ultimately, the primary constructor is always called first. Also you can’t use val or var defined arguments, as that would mean the field was only generated by that auxiliary constructor.  This guarantees all classes have the same structure
  • Case Classes – automatically creates all the fields for you as if you put the val keyword in front of each of them. (You can make the field a var if you like by pre-pending “var” to the definition.) You create them without having to use the “new” keyword. They also provide a nice default toString implementation. You cannot (from Scala 2.10 onwards) inherit from case classes 
  • Parameterized Types – at initialisation time, tells the compiler what type of object the container holds
  • Type Inference – don’t bother specifying the type explicitly, you don’t need to
  • Inheritance – inherit from another class using the extends keyword.  A derived class can only extend one base class, but a base class can be extended by any number of derived classes
  • Base Class Initialization – Scala guarantees all constructors are called within a class hierarchy during initialisation. If a base class has constructor arguments, then any class that inherits from that base must provide those arguments during construction. Derived-class primary constructors can call any of the overloaded, auxiliary constructors in the base class by providing the necessary constructor arguments in the call. You can’t call base-class constructors inside of overloaded derived-class constructors. The primary constructor is the “gateway” for all the overloaded constructors
  • Overriding Methods – provide an implementation in a derived class of a method in the base class (distinguished by the method signature).  The “override” keyword must be provided so Scala knows you intended to override. This gives us polymorphism just as you’d expect from Java. If you want to invoke the base-class version of a method, use the keyword “super”
  • Abstract Classes – like an ordinary class, except that one or more methods or fields is incomplete (i.e. without a definition or initialisation). Signified by the keyword “abstract” before the “class” keyword.  Use of “overrides” keyword is optional in definition of abstract methods in concrete subclasses
  • Polymorphism - If we create a class extending another abstract class A along with traits B and C, we can choose to treat that class as if it were only an A or only a B or only a C
  • Composition – just put something inside (i.e. as a field). Typically this is done with one (abstract) class and many traits with definitions but not implementations, deferring this implementation until the concrete base classes are created (aka “delay concreteness”)
  • Type Parameters – like Java Generics, from the perspective of the user 
  • Type Parameter Constraints – impose constraints on type parameters (again c.f. Java Generics)

So far, so (mostly predictable. Admittedly, there’s some syntactic sugar in it all (another way of thinking about the bits in italics) but there’s nothing to stretch the Java mind too much.  But there’s a lot more. The bits which go much further off-piste from a Java perspective (that I’ve come across so far) are as follows:

  • Functions as Objects – pass them around like any other object, and define methods to take functions as arguments
  • Function Literals – anonymous Functions, frequently only used once. defined by the ‘=>’ symbol. You can even assign an anonymous function to a var or val
  • Pattern Matching with Types – as well as pattern matching against values, you can pattern match against types
  • “Any” Typeany type, including functions
  • Pattern Matching with Case Classes – case classes were originally designed for this purpose.  When working with case classes, a match expression can even extract the argument fields
  • Enumerations (by extending Enumeration) – a collection of names. Enumeration is typically extended into an object. Within this object we need to define the set of vals assigned to Value (part of Enumeration) that the enumeration represents, enumeration fields and initialize each of them by calling the Enumeration.Value method.  Each call to Enumeration.Value returns a new instance of an inner class, also called Value. Furthermore you can and then alias the new enumeration object to the type Value (using the “type” keyword) to allow us to treat  as a type. For more information see Cay Hostmann’s “Scala for the Impatient”, pp. 65-66.
  • Enumerations (as a Subtype of a Trait) – we can also create something like an Enumeration by using a Tagging Trait.  Having taken this leap it doesn’t seem too great a leap to want to do other OO-type things with our Enumeration
  • Tuples – you can return more than one thing from a method, using a nice syntactic sugar to create and access and unpack them.  The same unpacking idiom is also accessible to case classes
  • Objects – by using the “object” keyword creates something you can’t create instances of – it already is an instance.  That means that “this” still works
  • Companion Objects – associated by having the same name as a class. If you create a field in the companion object, it produces a single piece of data for that field no matter how many instances of the associated class you make. Under the covers, creating a case class automatically creates a companion object with a factory method called “apply”. When you “construct” a new case class without using the “new” keyword Scala is actually calling “apply” (passing in the parameters you provided) and returning a new instance of the class
  • Traits – for assembling small, logical concepts, letting you acquire capabilities piecemeal rather than inheriting as a clump.  Ideally they represent a single concept. Defined using the “trait” keyword.  Mixed-in to a class by “extends” / “with” keywords (the former if it is the first, and there is no inheritance, the latter for all others).  You can mixin as many traits as you like, into concrete or abstract classes. Traits cannot be instantiated on their own. Traits can have values and functions, and be wholly or partially abstract if required (though they don’t have to be). Concrete classes which mixin traits must provide implementations of the abstract elements.  Abstract classes which mixin traits need not implement the abstract elements, but the concrete subclasses of them must.  Traits can extend from other traits, as well as abstract and concrete classes. If, when you mixin more than one trait, you combine two methods with the same signature (the name plus the type) you can (must) resolve these collisions by hand using super[Type].methodName
  • Tagging Traits – a way of grouping classes or objects together. Sometimes an alternative to Enumerations (combined with case objects). Indicated by the keyword “sealed” which indicates no more subtypes than the ones you see in the current source file
  • Case Objects – like a case class, but an object
  • Type Hierarchy – this is pretty fundamentally different from the one you’ll expect if coming from Java

There’s already a lot in what I’ve listed here, and from having used these elements, I can testify to the solid, expressive-but-terse code it lets you write.  But from reading ahead a little, and having listened in on conversations between people far brighter than myself, I know this is just the basics.  I’ll post back on those more in-depth topics once I come across them.

Onward!

Tuesday, 12 November 2013

Dianne Marsh Talks About “Demystifying Scala” with Scott Hanselman

Just a quick post this, but its been pointed out to me that Dianne Marsh (co-author of Atomic Scala and Director of Engineering at Netflix) recorded a recent episode of Scott Hanselman’s Hanselminutes.  In it she talks about demystifying Scala.  Definitely worth a listen.