Sometimes I get away from writing Scala for a while, and when I come back to it I see a piece of code that looks like this following example and I wonder, “What is Foo
, and how does this code work?”:
val f1 = Foo { println("hello from the `f1` instance") "this is the result of the block of code" }
Well, one way it can work is that Foo
can be a class that accepts a function parameter, and so everything inside those curly braces is the argument to Foo
. For example, this code shows how a Foo
class can be defined to accept a function as a constructor parameter:
case class Foo[A, B](f: A => B) { // more code here ... }
That code says that Foo
is a Scala case class that takes one constructor parameter, which is a function that transforms a generic type A
into a resulting generic type B
.
Going back to the first code I showed, everything inside the curly braces is that first argument to Foo
:
Informally speaking, everything inside a set of curly braces in Scala can be thought of as “a block of code,” and typically that block of code has some return value, such as "hello"
in this example.
Complete source code
The following source code provides a complete example of how this works:
case class Foo[A, B](f: A => B) { println(s"f = $f") //printed 1st } object AnonymousClassTest1 extends App { val f1 = Foo { i: Int => // printed 2nd println("hello from the anonymous function") i * 2 } // printed 3rd val result = f1.f(10) println(s"result = $result") }
I didn’t have anything particular in mind for this example, so I just added some print statements to show how this works. A good question at this point is, “What do you think the output of running this code will be?”
If you thought that the output would look like this, congratulations:
f = anon_classes.AnonymousClassTest1$$$Lambda$6/604107971@27f674d hello from the anonymous function result = 20
Another example: passing in a function
As another example, I could have passed a real (named) function into Foo
. To do this, first I create a function:
def double(i: Int): Int = { println("hello from a named function") i * 2 }
The next step is a little tricky if you’ve never seen it before. Here I created a function named partiallyAppliedDouble
:
val partiallyAppliedDouble = double(_)
What’s going on here is that double normally expects an Int
input parameter, but I’ve basically said, “I’m not going to give you an Int input parameter, and in fact, what I’m going to do is create a function named partiallyAppliedDouble
, and partiallyAppliedDouble
is now primed and ready to take an Int
input parameter.” In fact, I can now give partiallyAppliedDouble
a value like 21, and it will print 42:
println(partiallyAppliedDouble(21)) //prints 42
Now, because partiallyAppliedDouble
is a function that takes and Int
input parameter and returns an Int
, I can pass it into Foo
, like this:
val f2 = Foo(partiallyAppliedDouble)
This is almost exactly what I had in the first example above, except this time I passed in a named function, and in the first example I passed in an anonymous function (also known as a “lambda”). The rest if the code is the same as before:
val result2 = f2.f(10) println(s"result2 = $result2") //prints 20
Note that I could have also written the first part of that code like this:
val f2 = Foo(double(_))
but I wanted to take a moment to explain the partially-applied function part of it.
I went over this part of the example pretty fast here, but I take the time to explain things more slowly (and clearly) in my book, Functional Programming, Simplified.
Summary
Again this was nothing major today, I just wanted to refresh my memory on how anonymous classes in Scala work. I’m used to seeing anonymous classes used in Java GUI code, but I’ve also seen it a fair amount in Scala code recently.