I am developing Play application and I've just started with Scala. I see that there is this word Action
after the equals sign in the function below and before curly brace.
def index = Action {
Ok(views.html.index("Hi there"))
}
What does this code do? I've seen it used with def index = {
but not with the word before the curly brace.
I would assume that the name of the function is index
. But I do not know what the word Action
does in this situation.
This word is a part of Play Framework, and it's an object, which has method
apply(block: ⇒ Result)
, so your code is actually:Your
index
method returns an instance of the classAction[AnyContent]
.By the way, you're passing a block of code
{Ok(...)}
toapply
method, which (block of code) is actually acts as anonymous function here, because the required type forapply
's input is not justResult
but⇒ Result
, which means that it takes an anonymous function with no input parameters, which returnsResult
. So, your Ok-block will be executed when container, received your instance of classAction
(from index method), decided to execute this block. Which simply means that you're just describing an action here - not executing - it will be actually executed when Play received your request - and find binding to your action inside routing file.Also, you don't have to use
def
here as you always return same action -val
orlazy val
is usually enough. You will need adef
only if you actually want to pass some parameter from routing table (for instance):Another possible approach is to choose Action, based on parameter:
But uasually you can use routing table itself for that, which is better for decoupling. This example just shows that
Action
is nothing more than return value.Update for @Kazuya
GWT/Scala.js use simillar approach for client-server interaction. This is just one possible solution to explain importance of the parameter "methodName" passed from routing table. So, action could be thought as a wrapper over function that in its turn represents a reference to OOP-method, which makes it useful for both REST and RPC purposes.
The other answers deal with your specific case. You asked about the general case, however, so I'll attempt to answer from that perspective.
First off,
def
is used to define a method, not a function (better to learn that difference now). But, you're right,index
is the name of that method.Now, unlike other languages you might be familiar with (e.g., C, Java), Scala lets you define methods with an expression (as suggested by the use of the assignment operator syntax,
=
). That is, everything after the=
is an expression that will be evaluated to a value each time the method is invoked.So, whereas in Java you have to say:
In Scala, you can just say:
Of course, the expression is usually more complicated (as in your case). It could be a block of code, like you're more used to seeing, in which case the value is that of the last expression in the block:
Or it might involve a method invocation on some other object:
The latter is, in fact, exactly what's going on in your specific example, although it requires a bit more explanation to understand why. There are two bits of magic involved:
apply
method, then you can treat the object as if it were a function. You can say, for example,Add(1, 2)
when you really meanAdd.apply(1,2)
(assuming there's anAdd
object with anapply
method, of course). And just to be clear, it doesn't have to be an object defined with theobject
keyword. Any object with a suitableapply
method will do.def ifWaterBoiling(fn: => Tea)
), then you can invoke the method likeifWaterBoiling { makeTea }
. The code in that block is evaluated lazily (and may not be evaluated at all). This would be equivalent to writingifWaterBoiling({ makeTea })
. The{ makeTea }
part just defines an expression that gets passed in, unevaluated, for thefn
parameter.Its the
Action
being called on with an expression block as argument. (Theapply
method is used under the hood).A simple example (from here) is as follows (look at comments in code):
Now you can use it to wrap any other action value:
Also, the case you mentioned for
def index = {
is actually returningUnit
like:def index: Unit = {
.