Saturday, September 26, 2009

Scala interpreter in Firefox' location bar

SimplyScala is awesome for trying out some quick Scala tricks. However, you can go one step further, and execute Scala one-liners in your Firefox location bar!

1. Create a bookmark to URL http://www.simplyscala.com/interp?code=%s
2. Associate a keyword to the bookmark. Mine is "scala", you can try something shorter like "s" or ">".
3. Now when you type "scala <expression>", the expression will be sent to SimlpyScala and evaluated. For instance, "scala List(1,2,3).reverse"

Why does this work? Whenever you have a keyword associated with a bookmark Firefox expands "%s" in the URL to the text following the keyword. Check this Lifehacker article for details.

The nice thing is that your bindings are kept in your session, so you can use variable names defined in previous invocations. There are inconveniences, for instance you cannot easily preview your history and it's hard to review inputs which are more than a couple of lines long.

I also find that in combination with URL-shortening services it's an acceptable alternative to using code snippet sharing sites like gist.github.com or paste.pocoo.org. The code is actually part of the URL, which makes sense for shorter code snippets. You don't have syntax highlighting, but you have the evaluated result readily available.

Wednesday, September 16, 2009

3 things you didn't know Scala pattern matching can(not) do

Since I started learning Scala, pattern matching has become a favorite feature. But powerful as it is, pattern matching has some limitations. On the other hand, there are some unexpected ways to use pattern matching.

Fake multiple assignment of tuples



You already knew you can initialize multiple variables using the tuple syntax:

val (a, b) = (1, 2)


I want to do the same with closure parameters, though. For example, to swap the elements of 2-tuples in a list:


List(1 -> "one") map {
t => (t._2, t._1)
}


Still, using numbered slots for tuples doesn't seem as readable. It would be great if we could easily assign variables with meaningful names to document the purpose of the elements of the tuple. Parameters are already packed in a tuple, so why can't I do this:


List(1 -> "one") map {
val (num, str) = _; (str, num)
}


Unfortunately this is not legal syntax. Of course, I can explicitly bind the tuple to a temporary variable and then decompose it:


List(1 -> "one") map {
t => val (num, str) = t; (str, num)
}


But this seems too verbose for Scala. Fortunately, there's a trick which can help. Pattern matches are actually instances of partial functions! The closures used for map, filter, etc. are functions, too. This means we can use a pattern match to bind variables to the closure parameters:


List(1 -> "one") map {
case (num, str) => (str, num)
}


Match the last element of a list



Decomposing lists in pattern matching is another power feature of Scala. You can match the first element of a list:


List(1, 2, 3) match {
case List(1, _*) => "yeah!"
}


The underscore-star (_*) symbol serves as a placeholder for the rest of the elements of the list. You can also do this:


List(1, 2, 3) match {
case 1 :: _ => "hurray!"
}


Which mimicks construction of the list using the cons operator. So what if I want to match on the last element instead of the first?


(1 to 9).toList match {
case List(_*, 8, 9) => "sure"
}


Hey, this seems like it's working! Not so fast, though:


(1 to 9).toList match {
case List(_*, 18) => "yeah, right"
}


In fact, in Scala 2.8 this syntax will trigger an error message: "_* may only come last"

How about using the alternative notation?


(1 to 9).toList match {
case _ :: 9 :: Nil=> "no way"
}


Unfortunately Scala expects the placeholder to be an element, not a list. The triple colon expects a list, will it work?


(1 to 9).toList match {
case _ ::: 9 :: Nil => "absolutely not"
}


Nope, this isn't even recognized by the compiler. While you're wondering why there is a ::: operator, but it's unknown to Scala in pattern matching, remember that ::, which is used in pattern matching, is actually a class. Furthermore, the syntax "a :: b" is in fact a more readable expression of "::(a, b)", which in turn is a short form of "call unapply on the matching expression and check if it decomposes to a and b".

And this, in short, is how the Scala black magic, called "extractors", works. But can we also use it to match on the last element of a list? Sure! Just define an object (let's call it "::>") and define its unapply method. The method expects a list and must return a tuple of the "init" part of the list and the "last".


object ::> {def unapply[A] (l: List[A]) = Some( (l.init, l.last) )}

List(1, 2, 3) match {
case _ ::> last => println(last)
}

(1 to 9).toList match {
case List(1, 2, 3, 4, 5, 6, 7, 8) ::> 9 => "woah!"
}
(1 to 9).toList match {
case List(1, 2, 3, 4, 5, 6, 7) ::> 8 ::> 9 => "w00t!"
}


Match structural types



Since you've heard of structural types, didn't you wish you could do this to find out whether a class has a certain method?


List(1) match {
case t: {def length: Int} => "cool!"
}


Unfortunately, here again we are fooled in thinking method checking happens when matching the class. It's not:


List(1) match {
case t: {def aoeu: Int} => "really?"
}


The reason for this is that the class type is erased to AnyRef. Unfortunately, there's no clean workaround for this- yet. This looks positively ugly:


List(1) match {
case t: {def aoeu: Int}
if t.getClass.getMethods.exists{_.getName == "aoeu"} => "not really!"
}


Do not despair, though- there's a chance that this feature is going to land in Scala sooner or later.