Showing posts with label scala. Show all posts
Showing posts with label scala. Show all posts

Tuesday, August 12, 2014

Scalarific FizzBuzz

This started as a lunchtime conversation about interviewing. I'm a big fan of FizzBuzz as a “screening” question: it weeds out the people that shouldn't be allowed near a computer (and, after conducting several hundred interviews, I can say that there's a depressingly large number of them, especially at a company without a preliminary phone screen).

For a Scala developer, what constitutes a good FizzBuzz? Clearly, it should be based around higher-order functions, such as a map() (and, as I don't consider myself a Scala developer, I'll leave the parentheses and dots in place):

(1 to 20).map(???)

A simple implementation might use an if expression:

def fbi(x: Int): String = {
    if ((x % 15) == 0) "fizzbuzz"
    else if ((x % 3) == 0) "fizz"
    else if ((x % 5) == 0) "buzz"
    else s"$x"
}

It gets the job done, but looks too much like Java. We need to add some Scala-specific syntax:

def fbm(x: Int): String = x match {
    case n if ((n % 15) == 0) => "fizzbuzz"
    case n if ((n % 3) == 0) => "fizz"
    case n if ((n % 5) == 0) => "buzz"
    case n => s"$n"
}

You can argue whether this is better or worse. It seems to me that it just wraps the previous if with more cruft.* As our conversation devolved, though, it led to the following implementation, which is about as far from Java as I can imagine:

object Fizz {
    def unapply(x: Int): Boolean = ((x % 3) == 0)
}
  
object Buzz {
    def unapply(x: Int): Boolean = ((x % 5) == 0)
}
  
object FizzBuzz {
    def unapply(x: Int): Boolean = ((x % 15) == 0)
}
 
def fbme(x: Int): String = x match {
    case FizzBuzz() => "fizzbuzz"
    case Fizz() => "fizz"
    case Buzz() => "buzz"
    case n => s"$n"
}    

Mind you, I don't think I'd want to hire someone who implemented FizzBuzz this way.


* You'll find a nicer match-based implementation at RosettaCode. Along with some versions that make my extractor-based implementation look sane.

Friday, November 8, 2013

Review: Coursera's "Functional Programming Principles in Scala" by Martin Odersky

I just completed this class as part of my introduction to Scala. For those of you that aren't familiar with Coursera, it is one of a growing number of organizations that provide free online education, taught by professors from well-known universities. These organizations are part of a revolution in education, one that might just change the way we think about post-secondary education. At present, they provide an excellent way to sharpen one's skills.

This was my first Coursera class, and I was impressed by its basic mechanics: the class website, lectures, and assignments. I'm not certain how much of this is attributable to the Coursera team, and how much to Martin Odersky's grad students. I expect the automated grading tools to be the latter, but the general website to be shared between classes. Unfortunately, it appears that you can't look at a class' content without signing up, so I'll have to wait for my next class to make a comparison.

If you're thinking of taking an online class, I caution you not to underestimate the time commitment. This class was advertised as 5-7 hours a week, which doesn't seem like much until you try to fit it into your schedule. I gave over a couple evenings a week for lectures, along with several hours for assignments (usually before work, but occasionally on weekends). Since I got my undergraduate degree in a part-time program, taking two classes a semester in addition a full-time job as a software developer, I didn't think I'd have trouble with the workload. I don't think my lifestyle has changed much in the intervening dozen years, but it was tough to fit this class in.

On to the class. It was seven weeks long, with a couple of hours of lectures each week and a total of six programming assignments (some spanning more than a week). Lectures were broken into segments of 10-30 minutes, focusing on a single topic. However, they weren't simply videos: each lecture had one or more “quizzes” embedded within it, requiring viewer interaction and occasional typing. As a result, you'll need access to the Internet; they aren't something that you can complete on a plane.*

Assignments are packaged as ZIP files containing skeleton source code and an Eclipse project configuration. They can also be built using the sbt build tool, and you need to use this tool to submit them. The source code provides stub methods for the expected implementation and a few minimal unit tests; you are expected to add more tests while completing the assignment. When you submit an assignment, an automated grading tool runs a battery of unit tests and a style check (don't use short-circuit returns!). If you fail any of the unit tests, you'll see the test output but not the test itself; sometimes it's a challenge to figure out what the grader is trying to test.

If you've watched the MIT 6.001 lectures by Abelson and Sussman (aka the SICP lectures), you'll find the Odersky lectures very similar, at least at the beginning (to the point of using many of the same examples). Another point of similarity is that the lectures do not focus on the language itself. For Scheme, that's not so bad: the language is simple. For Scala, you'll want to have an introductory book by your side (for example, Odersky's own Programming in Scala). You'll also want to keep the Scala Standard Library documentation open.

My chief complaint with the course is that it occasionally focused on functional programming to the detriment of good programming, particularly in the assignments. For example, the assignment on Huffman coding used classes as mere data containers, moving all of the logic into standalone functions. Within the context of the assignment — pattern matching — this approach makes sense. However, in the real world I would want to see this implemented with runtime polymorphism: pattern matching in this example is just a glorified switch.**

That said, I highly recommend this class. If you haven't worked with a functional language in the past, you'll find the ideas new and (hopefully) interesting. Even if you have used a functional language, you might find something new: for me, the assignment on “functional sets” (implementing the Set abstraction in pure code) was particularly interesting. And if you're using Scala professionally, I think it's worthwhile to see how the creator of the language approaches problems.

I'll finish with an unexpected insight: Java's generics implementation — and in particular, that parameterized collections don't behave like arrays — was 100% intentional. I'm not sure if you'll be able to watch this lecture, but if you do, you'll see (about 7 minutes in) Odersky explain how Java arrays are bad because they don't allow the compiler to catch certain type errors (the same material is also covered in Programming in Scala). After seeing this, I dug up the JSR-14 spec, and saw that yes, Odersky was one of the people responsible.


* Actually, it may be possible to watch on a plane; a quick session with Firebug indicates that the videos are straightforward HTML5. I haven't looked at the code behind them, so it's possible that the quizzes are implemented in JavaScript.

** My concern is that the assignments distribute logic rather than encapsulate it. A more egregious example, but one less open to explication, is in a later assignment: defining a simple type alias to represent a list of pairs. What the simple alias does not convey, however, is that the list must remain sorted. An object-oriented approach would maintain this invariant in the class; consumers would never see/create an unsorted list. The functional approach, by comparison, requires every function that transforms the list to maintain the invariant.

Friday, October 18, 2013

Immutability and Thread-Safety, Part 2

I've had a few offline conversations about my last post, and decided to dive a little deeper into concurrency and immutability. As an example, I'll use a shared map: the sort of thing you might use to hold session data in a web application. The first implementation simply wraps Scala's immutable.Map:

class SharedMap {

  var theMap : Map[String,String] = Map.empty;

  def size = theMap.size

  def get(key:String) = theMap.get(key)

  def put(key:String, value:String) {
    theMap = theMap + (key -> value)
  }
}

Because theMap is immutable, you have the following guarantee: put() will not interfere with get(). If they happen to be called at the same time, the get will use the old instance of the map, and not have to worry about partial changes due to the put. This is a powerful guarantee, but it does not mean that this code is thread-safe.

The problem is that this implementation allows an update race: if two threads call put() at the same time, they make their own immutable changes to the same immutable base map. But neither's changes include the other's, and only one change will be saved as the new base map.

Appending an item to an immutable map is a very fast operation. So fast that you might never hit the update race in testing. But in a production environment, with dozens or hundreds of concurrent updates, it is bound to happen, and you'll lose data. To see this happen rather spectacularly, run the following program.*

object ConcurrentUpdateRunner extends App {

  val map = new SharedMap

  val pool = java.util.concurrent.Executors.newFixedThreadPool(20)

  val futures = (1 to 100).map(ii => {
    val callable = new java.util.concurrent.Callable[String]() {
      def call() = {
        val x = Thread.currentThread.getName
        map.put(ii.toString, x)
        x
      }
    }
    pool.submit(callable)
  })

  val results = futures.map(_.get)
  println(s"number of executed Callables: ${results.size}");

  println(s"final map size: ${map.size}")
}

So what can you do?

One option is to introduce synchronization. For a simple data structure like this map, that's the route that I'd take, although some people see any use of synchronization as taboo.

def get(key:String) = theMap.get(key)

def put(key:String, value:String) {
  synchronized { theMap = theMap + (key -> value) }
}

Note that I just synchronized put(), something that I warned against in a previous post. But that warning applies only to mutable data structures. Since the underlying map in this example is immutable, we can get use half-synchronization without worry, and avoid contention between get and put.

A second alternative is to forego the Scala library, and use a ConcurrentHashMap.

At first glance, this appears to be a perfect solution: you don't have to think about concurrent access, just rely on the fact that Doug Lea understands it far better than you. However, a ConcurrentHashMap only guarantees thread safety of individual gets and puts. For our trivial map example this is sufficient. For most real-world applications it isn't, because you need atomic updates of data that's already in the map.

A third option, which I mentioned in my last post, is to introduce a message queue between the map and its consumers. This is not a particularly novel idea: Odersky suggests it in Programming in Scala (in the section “Good actors style”), and Armstrong uses a similar example in Programming Erlang. Here is one possible implementation, using Scala actors (which, although deprecated, are usable without the need for an additional library in the classpath).

class ActorMap1 {

  case class SizeMessage
  case class GetMessage(key:String)
  case class PutMessage(Key:String, value:String)

  val theActor = new DaemonActor {
    var theMap : Map[String,String] = Map.empty;

    def act() {
      loop {
        receive {
          case SizeMessage() => {
            sender ! theMap.size
          }
          case GetMessage(key) => {
            sender ! theMap.get(key)
          }
          case PutMessage(key,value) => {
            theMap = theMap + (key -> value)
          }
        }
      }
    }
  }

  theActor.start

  def size = {
    val fut = theActor !! new SizeMessage
    fut.apply
  }

  def get(key:String) = {
    val fut = theActor !! new GetMessage(key)
    fut.apply
  }

  def put(key:String, value:String) {
    theActor ! new PutMessage(key, value)
  }
}

This example adds quite a bit of complexity to the shared map: new classes to hold messages for the actor, and a facade object to handle the communications. And it still has a significant flaw: there's only one loop, handling both gets and puts. We've achieved thread safety, at the cost of introducing a bottleneck for concurrent operations.

In the case of an in-memory map, this bottleneck probably isn't significant. Unless you have dozens of threads constantly hitting the map, to the exclusion of other actions, the occasional waits will go unnoticed. But what if this map is actually a write-through cache for a database or socket? In that case, the put will take significant time, and contention becomes a real possibility. To resolve this problem, we can add another actor to the mix.

class ActorMap2 {

  case class SizeMessage
  case class GetMessage(key:String)
  case class PutMessage(Key:String, value:String)
  case class InternalPutMessage(Key:String, value:String)

  val getActor = new DaemonActor {
    var theMap : Map[String,String] = Map.empty;

    def act() {
      loop {
        receive {
          case SizeMessage() => {
            sender ! theMap.size
          }
          case GetMessage(key) => {
            sender ! theMap.get(key)
          }
          case InternalPutMessage(key,value) => {
            theMap = theMap + (key -> value)
          }
        }
      }
    }
  }

  val putActor = new DaemonActor {
    def act() {
      loop {
        receive {
          case PutMessage(key,value) => {
            // some long-running operation
            getActor ! InternalPutMessage(key, value)
          }
        }
      }
    }
  }

  getActor.start
  putActor.start

  def size = {
    val fut = getActor !! new SizeMessage
    fut.apply
  }

  def get(key:String) = {
    val fut = getActor !! new GetMessage(key)
    fut.apply
  }

  def put(key:String, value:String) {
    putActor ! new PutMessage(key, value)
  }
}

Yet more complexity, and it still isn't complete: put() doesn't have any way to signal the caller that an error occurred, and real-world actor systems need supervisors. Plus, there's still the possibility that parts of the application will hold onto stale data (a problem that can never truly be solved).

But that was the entire point of my last post. It isn't easy to correctly implement concurrent applications, and immutable data structures don't help you solve the bigger issues. If you rely on them to do so, you will be burned. You need to understand how the larger application mutates state, and choose an appropriate strategy for managing those mutations.

Finally, although in this example it appears to be a case of hunting mosquitoes with a shotgun, decomposition into independent actors does solve many of the bigger problems of concurrency. But that's simply because it forces you into the techniques of information hiding and limited interfaces that have been part of software engineering since the 1970s.


* I used a threadpool, rather than actors, to have better control over the number of threads. I'm also running on a multi-core processor, which means that I'm really hitting the map from multiple threads at the same time. Switching between single-core and multi-core machines tends to highlight different threading bugs.

Monday, September 16, 2013

Thoughts on Scala Before Using It

While I think Go is my future, I'm about to embark on a project using Scala. So I've spent the last week reading Programming in Scala, by Martin Odersky et al. And I've signed up for the Coursera class Functional Programming Principles in Scala, which starts today. I do have some experience with a functional approach to programming, so it's not a completely foreign land. But I lean strongly toward an object-oriented, message-driven (push) approach to decomposing problems; the functional (pull) approach will take some getting used to.

This is the first of two posts. I'll write the second six months or so from now, after I've spent enough time with the language to feel that I “get it” — or don't. Here, then, are my first impressions, after diving just below the surface.

Things that I like

Implicit conversions
I'm not sure that no longer having to call toString() explicitly (with a null check) is a reason to use Scala, but it's close. Conversion code is almost always clutter, sometimes quite complex clutter. Being able to move that clutter into a method, and rely on the compiler to invoke the method as needed, is fabulous.
Null is an object
Java's concept of null, and the need to explicitly test for null-ness, is one of the less pleasant things that it inherited from C. It's a leading cause of code clutter, and drives the creation of utility classes that provide null-safe operations. I haven't looked at all the methods that Scala's Null provides, but equals() is enough to make me happy.
Traits
There's a well-worn adage to “favor composition over inheritance.” This can result in a plethora of function calls that simply call a delegate, violating the adage “don't repeat yourself.” Traits make composition easy, creating delegates and then hiding them behind a curtain of syntactic sugar. I will say that I've looked behind that curtain, and don't think I ever want to find myself debugging them.
For Comprehensions
This is a neat feature, which I first saw in Erlang. It makes for a very simple way to apply filters to a list's elements before taking some other action on those elements, and I agree that it largely replaces break and continue.
Match expressions
Another feature that has its roots in Erlang (or earlier inference languages). I'm especially impressed by constructor matching, which leverages the immutability guarantees of a “case” class (again, I looked behind the curtain: while I think the code generation could use some work — particularly reuse of local variables — the approach is elegant).

Things that I don't like

Optional semi-colons
Are semi-colons really that evil? They certainly aren't hard to type: the key is right there on the home row (at least on a US keyboard). Yet Scala, like JavaScript, makes them optional. Of course, the compiler still needs to decide where to end a statement, so has to have other rules. In the case of Scala, the end of a line is the end of a statement, unless it doesn't make sense for a statement to end at that point.

I personally find this rule annoying for complex expressions, which I want to format on multiple lines, with the operator first on the line (so that it's obvious). Scala, however forces me to put the operator on the end of the line, where it's hard to see, because otherwise the compiler thinks the preceding term is the end of the current statement. Perhaps this is a not-so-subtle nudge toward simpler expressions, but there are some cases where a real-world rule has lots of terms; it's just easier to read if the terms are on separate lines, even if they're function calls.

OK, that's just me whining. But, like other languages that attempt to do away with statement separators, Scala sometimes requires you to use them. One example is a variable declaration that precedes a standalone block. Not that you're likely to use a standalone block unless you're demonstrating scoping rules. But if you have to do it sometimes, why add the mental load of remembering when those times are?

Too many symbolic operators
This was one of my first impressions of Scala, after seeing a JUG presentation several years ago. I'm neutral on the subject of operator overloading: it can be abused, but I've seen enough elegant overloads to think it has value. My issue with Scala is that any arbitrary string of apparent line noise is an operator. This creates unnecessary mental load: is “::” really better than “concat”, or “<-” better than “in”? I don't think so.
Precedence and associativity rules
Languages like C++ provide operator overloading: you can create new definitions for existing operators, which follow the rules of the language's grammar. Scala provides operator creation: syntactic sugar that makes arbitrarily-named methods look like they're part of the language. But the precedence and associativity rules that underly this feature are Byzantine to say the least. There's really no excuse for this: if you're going to put programmers in the position of being language designers, you need to give them the tools to do the job properly. In this case, explicit definitions of a function-operator's precedence and associativity..
Underscores as parameter placeholders
This is, I think, conciseness taken too far: rather than define the parameters of a function literal, you use underscores in the function body; each underscore takes the place of a sequential parameter. Intellectually, I get it. Looking at code filled with underscores, I don't. And if you want to use the same parameter in multiple places, you're required to explicitly define it.

Better, in my opinion, would be an explicit parameter syntax. Personally, I like the way the shell does it: $1, $2 and so on for individual params, $* to represent all params.

Things that have me scratching my head

Primary constructor parameters and their relationship to fields
Here's the example given by Odersky (I'm copying this from the book, so errors are mine):
class Rational(n: Int, d: Int) {
  // ...
}
This makes perfect sense: by defining the class' member variables as constructor parameters, you save the boilerplate of explicit variable definitions and assignments. But then, a page later, he shows that they're not really fields in the Java sense: it's a compile-time error if you try to access them using another instance of the class:
def add(that: Rational): Rational = 
  new Rational(n * that.d + that.n * d, d * that.d)
Now, if you look in the actual class code, you'll find that these constructor parameters are, in fact, fields in the class. Unless you continue the example, create explicit fields, and don't otherwise use the constructor parameters in your code. For a language that eschews boilerplate, I just don't get it.

It is, however, something that I've seen before: Scala's primary constructor looks and acts just like a JavaScript constructor function (which is something that experienced JavaScript programmers don't often use). I can understand the pattern for JavaScript, which doesn't have rigidly-defined classes, but it doesn't make much sense for Scala.

Not everything is an expression
I've never liked the separation between statements and expressions, and Scala erodes that boundary in many places. The if expression is one such place, function returns are another. And yet, the boundary remains in several surprising places: a while statement is one example, but the truly baffling one is variable assignment. While I don't often use constructs such as x = y = 0, I do use the Java (and C) idiom of assigning a variable and testing its value (eg: (s = in.readLine()) != null)). But not in Scala.

The only reason that I can imagine is that such behavior is functionally impure: I should use an iteration function that calls another function to process the iterated value, so the language will push me in that direction. I suspect the same reasoning is why while doesn't return a value: we shouldn't be using while.