Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What Scala concepts are being used to make Scalatra DSL work?

Tags:

scala

scalatra

I'm trying to get into Scala by trying to use Scalatra. I finished Martin Odersky course on coursera some time ago but I still have a hard time understaning how this works:

package com.example.app
import org.scalatra._

class HelloWorldApp extends ScalatraFilter {
  get("/") {
    <h1>Hello, {params("name")}</h1>
  }
}

This example is taken from Scalatra main page: http://www.scalatra.org/

How this statement is executed:

get("/") {
    Hello, {params("name")}
}

Is {} a parameter of get() method? Can you explain what features of Scala language are in use here? Pointers at Scalatra source code would be perfect defining this would be perfect.

like image 657
atok Avatar asked Jul 11 '14 08:07

atok


2 Answers

get is defined in CoreDsl as follows

def get(transformers: RouteTransformer*)(block: => Any): Route

So, get takes two parameters, a sequence of route transformers (strings are implicitly converted into route transformers) and a parameterless method that outputs something of type Any. The interesting part here is this second parameter.

The first thing to understand is that parameterless methods as function arguments are handled specially in Scala, namely as call-by-name, see Automatic Type-Dependent Closure Construction and also Scala Language Reference, Section 6.6, p. 78, which is p. 86 of the PDF:

The case of a formal parameter with a parameterless method type => T is treated specially. In this case, the corresponding actual argument expression e is not evaluated before the application. Instead, every use of the formal parameter on the right-hand side of the rewrite rule entails a re-evaluation of e. In other words, the evaluation order for =>-parameters is call-by-name whereas the evaluation order for normal parameters is call-by-value.

The second aspect is that in function application, arguments can be enclosed either in () (the "regular" arguments) or {} (more precisely, in this case they must be block expressions, and they can even start on a new line), see Scala Language Reference on Function Application, Section 6.6 on p. 77, which is p. 85 of the PDF.

Note also how these two features are a significant part of what makes Scala an attractive language for defining DSLs (or new keyword-like features).

Parts of the following question might also be interesting What's the difference between multiple parameters lists and multiple parameters per list in Scala?

like image 72
godfatherofpolka Avatar answered Nov 08 '22 06:11

godfatherofpolka


Is {} a parameter of get() method?

Yes. get will have two parameter lists. One is for the path "\" and the other for the block to execute. Blocks are enclosed in {}, parameters in (). So you would seem to have to call it as

class HelloWorldApp extends ScalatraFilter {
  get("/") ({
    <h1>Hello, {params("name")}</h1>
  })
}

but there's some syntactic sugar that allows a single parameter in {} to be passed without having to add the (). You see this more commonly in things like

myList foreach { do_something() }

It's a very useful feature for writing what look like, and are used like, new control structures but are actually just functions.

like image 20
The Archetypal Paul Avatar answered Nov 08 '22 05:11

The Archetypal Paul