Thursday, September 24, 2009

andThen andThen andThen... Scala, where's my car?

When I saw Dude Where's My Car?, several years ago with my wife (who is Chinese), she started laughing right as they pulled into the parking lot of a Chinese restaurant. I had no idea why, but she said to wait until the end of the scene. In the scene, after they order each item, a voice from the speaker says, "and then?" and continues after they run out of things to order until Ashton Kutcher eventually destroys the speaker in frustration. When the scene was over, I asked her why she started to laugh at the beginning of the scene. She said she had heard people quoting that at work, but she never realized that the Chinese name of the restaurant, which she saw at the beginning of the scene, was "And Then."

Appropriately, Scala defines infinite loops in actors using andThen. Here's how...

In Scala, one way to compose functions is "f andThen g", which is the same as
def newFunc[T](x: T) = g(f(x))
You can think of it as "evaluate f(x) and then evaluate g with that result". It's an easy way to chain functions and it's good for noncommutative operations, where "order matters," like matrix operations (the same type of idea you would use in implementing a safe navigation operator {quickly ducking for cover}). For instance, if you want make a function that takes a matrix, transposes it and inverts it and then returns the determinant, you could write that like this:
def transInv = transpose andThen invert andThen determinant
Those not familiar with functional programming will note the lack of arguments and return type in the definition of transInv. TransInv gets its arg types from transpose and its return type from determinant, so you can still use transInv(myMatrix). The definition of Function1[A, R].andThen is (here, Function1 takes an argument of type A and returns a result of type R):
def andThen[A](g: R => A): T1 => A = { x => g(apply(x)) }
Scala defines infinite loops in actors using andThen:
def loop(body: => Unit): Unit = body andThen loop(body)
So, if want to simulate the scene in Dude, Where's My Car?, using an actor, you can say:
loop {choose}
which translates to:
((_: Unit) => choose) andThen (_ => choose) andThen (_ => choose) andThen...

No comments:

Post a Comment