24

I'm having difficulty finding specific answers to what I know is something trivial. I would like to understand how blocks work in Scala. I come from a java/ruby background and it seems that scala has an entirely different way of using blocks.

The following code is from the Play! Framework website. I would like to understand what Action is semantically. Is it an object or a function that accepts a block, or perhaps neither.

object Application extends Controller {

  def index = Action {
    Ok(views.html.index("Your new application is ready."))
  }

}

If it is a function, perhaps it's syntactic sugar for the following (in which case how does scala pass around blocks behind the scenes):

  def index = Action({
    Ok(views.html.index("Your new application is ready."))
  })

Or is it some scala syntax I'm unaware of.

Any references to Scala source code would help me understand how this is working behind the scenes.

b1nd
  • 370
  • 6
  • 12

2 Answers2

25

You would be better to think about scala blocks as java anonymous classes (e.g. like Guava Functions) rather than as ruby blocks. Actually speaking, if you decompile scala code you will see more or less the same code (taken from Guava examples):

Function<String, Integer> lengthFunction = new Function<String, Integer>() {
  public Integer apply(String string) {
    return string.length();
  }
};

The difference is that scala provides a lot of syntax sugar and allows you to write above code as:

val lengthFunction = { string: String => string.length }

As for a specific Action example:

def index = Action({
    Ok(views.html.index("Your new application is ready."))
  })

Here Action is likely object with apply method. Another scala sugar: language allows you to write Foo(bar) and mean Foo.apply(bar). Next, you can drop round braces when your call isn't ambiguous, so yes, it is actually a method that got called like:

def index = Action({
    Ok(views.html.index("Your new application is ready."))
})

And have something like this as a signature:

object Action {
  def apply(block: => Result) = ???
}

As already said by @yan, it is scala way to say hey, I'm a function that accept another function that produces Result

Desugared invocation will look like

def index = Action.apply(new AbstractFunction[Result] {
        def apply() = Ok.apply(views.html.index.apply("..."))
})
Community
  • 1
  • 1
om-nom-nom
  • 62,329
  • 13
  • 183
  • 228
8

There are a few things going on here. Action is an object which implements an apply() method, what is what gets called when you treat the object as a function. There are a few apply() implementations. The first implementation uses a by-name parameter.

Scala supports a concept known as 'by-name parameters', which are like normal parameters except they are only evaluated when the code that references them is executed. They help with creating constructs which appear like they are part of the language without resorting to macros. In this case, the block surrounding Ok(..) is just a regular block of statements, with the last one's value being used as the value of the block. The example you provided will work as well without the braces. You're essentially just passing the result of Ok's apply method to Action's apply method.

The second version of apply() does indeed take a full anonymous function which maps a Request to a Result. In this case, you can pass an anonymous (or named) function.

yan
  • 20,644
  • 3
  • 38
  • 48
  • Thanks for the reply. So from what i'm gathering, this is syntatic sugar for Action.apply(). Removing the sugar, what would the entire statement look like? – b1nd Sep 25 '13 at 14:35
  • The statement as you have it is essentially `Action.apply(Ok.apply(views.html.index("Your new application is ready.")))`. If you look at the definition of `apply()` in the URL I supplied, you'd notice an arrow prior to the type of the parameter. That just marks it a 'by-name' parameter, described above. (Also, it's no coincidence that the syntax for by-name looks like that of an anonymous function with no arguments) – yan Sep 25 '13 at 14:37
  • Link to play doc is broken by the way. Occasionally, SO parser messes up links that contain dollar sign. – om-nom-nom Sep 25 '13 at 15:40