Question

In 'Programming in Scala, Second Edition' at page 410 you can find class Simulation which have the following method:

private def next() {
  (agenda: @unchecked) match {
    case item :: rest =>
      agenda = rest
      curtime = item.time
      item.action()
  }
}

I'm curious why Odersky implemented this with pattern matching rather than just like that:

private def next() {
  val item = agenda.head
  agenda = agenda.tail
  curtime = item.time
  item.action()
}

Is pattern matching so efficient that it doesn't matter at all? Or it was just not so perfect example?

Was it helpful?

Solution

Normally I'd write it the way you did. (Even though pattern matching is quite efficient, it is not as efficient as head/tail.) You'd use pattern matching if

  1. You wanted to practice pattern matching
  2. You wanted a MatchException instead of a NoSuchElementException
  3. You were going to fill in other cases later.

OTHER TIPS

There are a couple reasons:

  1. Part of the point of the book is to get you thinking in Scala (functional) terms; pattern matching is the functional-programming equivalent.

  2. Pattern matching and the functional approach are the natural pattern in Scala, and allow things like concurrency in a natural way; learn that pattern and your Scala programs will be ready for more advanced uses.

Pattern matching is more idiomatic in Scala, and more easily protects you from boundary conditions.

In the code

private def next() {
  val item = agenda.head
  agenda = agenda.tail
  curtime = item.time
  item.action()
}

Both agenda.head and agenda.tail will throw a NoSuchElementException exception if agenda is an empty list, so to make it actually work you need to add a check for that.

The pattern matching version actually has a similar issue (as noted in th comments), but I find the fix cleaner, as all you have to do is add another pattern:

private def next() {
  (agenda: @unchecked) match {
    case item :: rest =>
      agenda = rest
      curtime = item.time
      item.action()
    case _ => {}
  }
}

My guess is first that exceptions are not a worry here, there is probably some check before this "next" method is called. In fact, this is probably the reason for the "unchecked" annotation too, so he can really not have to put an extra case _ =>. I think the reasoning was more that he wanted to use "unapply". An alternative here without the pattern matching, but also without head and tail could be something like:

private def next() {  
    val item :: rest = agenda
    agenda = rest
    curtime = item.time
    item.action()
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top