Scala: Generate a block that conditionally runs another block - scala

In the Circumflex framework, you can map an URL to a block like this:
get("/foo") = {
"hello, world!"
}
which, when browsing to /foo, will show the given string as expected. Now, to write a complete web application, you almost always need some form of authentication and authorisation. I'm trying to write some kind of wrapper for the above construct, so I can write this:
get("/foo") = requireLogin {
"hello, world!"
}
The requireLogin method would then check if the user is logged in, and if yes, execute the given block. If not, however, it should do a redirect to the login page.
Now I somehow can't get the syntax right (i'm still a Scala newbie). How would you do this in a generic fashion?

Try something like this:
def executeMaybe[A](work: => A): Option[A] =
if (util.Random.nextBoolean)
Some(work)
else
None
This executes the passed code with probability 0.5, returning Some(<result delivered by work>), or returns None is the other cases. You can call it either like this:
val v = executeMaybe(42)
or with block notation:
val v = executeMaybe {
// do some work
// provide return value
}
The trick is to use a by-name parameter, signalled by the => symbol. Read more e.g. here: http://daily-scala.blogspot.com/2009/12/by-name-parameter-to-function.html

The way I asked it, Jean-Philippe's answer is correct.
But here's some information specific to Circumflex:
In the Circumflex RequestRouter, the following can be used to implement the required method:
def requireLogin (f: => RouteResponse ): RouteResponse = {
if(loggedIn) {
return f
}
else {
return sendRedirect("/login")
}
}
The reason behind this was getting clear with the hint from Jean-Philippe's answer, and once I remembered that the following call isn't an assignment of a block to some internal data, but is mapped to another method call instead.
So, the call
get("/") = {...}
is actually mapped to this:
get.update("/", {...})
The block is passed in as a By-Name parameter, so the return value of requireLogin must be the same - which, for Circumflex, is RouteResponse, and not a function.

You also can use j2ee container authentication with <login-config> and <security-constraint> stuff inside web.xml

Related

Possible forms of function literals in Scala

I was looking at some Scala 2 code in a project I am working on that seemed very strange to me.
Suppose there is a method that takes a function as an argument like:-
def invoke(
request: Request,
block: (Request) => Future[Result]
)
The normal form of function literal that I am familiar with, would allow us to call invoke like this:
obj.invoke(
request,
(req: Request) => {
// a bunch of code
}
)
However, I am looking at some code where the sole argument is within the braces like:
obj.invoke(
request,
{
req: Request =>
// a bunch of code
}
)
Are the above two styles synonymous? If not then what is happening in the second way and when should it be used?
I am pretty new to Scala and have been reading from "Programming in Scala" but don't recall anything similar to the code I wrote above.

scala reassignment to val in Option Class

My code looks like:
case class SRecord(trialId: String, private var _max:Int) {
def max=_max
def max_=(value:Int):Unit=_max=value
}
Then later on I apply a function onto it:
def groupSummaryRecords(it:Iterator[Option[SRecord]], optionSummary:Option[SRecord]):Option[SRecord] = {
var max=0;
var sRecord1 : Option[SRecord] = None
var i=0
while(it.hasNext) {
var sRecord:Option[SRecord] = it.next();
if(i==0) {
sRecord1 = sRecord;
}
..
}
sRecord1.max=max; // getting 'reassignment to val' compilation error
..
}
Why am i getting this compilation error, and how to fix it ?
If I instead change sRecord and sRecord1 instances to be of type SRecord instead of Option[SRecord] as well as the method signature, it all works fine however.
But in some cases I may have a null SRecord hence the use of None/Some. I am new to Scala, using Option/Some all over feels like a real pain if you ask me, i am just thinking of removing all this Option nonsense and testing for 'null' in good ol' Java, at least my code would work ??!
With the line sRecord1.max=max you are trying to call the max method on an Option[SRecord], not an SRecord. You want to access the contained SRecord (if any) and call the method on that, which can be done using foreach:
sRecord1.foreach(_.max=max)
which is desugared to:
sRecord1.foreach( srec => srec.max=max )
(the actual name "srec" is made up, the compiler will assign some internal name, but you get the idea). If sRecord1 is None, this won't do anything, but if it is Some(srec), the method execution will be passed in to operate on the contained instance.

Capture a return value for logging and then return the value in Scala

What is the most 'scala-ic' way to capture a value (possibly one that is not idempotent) for logging and returning the same value.
I can think of 'return' statement the only way to do it, but apparently using 'return' should be avoided in scala .
Use case:
def myfunc(argument) : ReturnType{
val response:ReturnType = dependency()
// dependency() is not idemptotent
// so calling more than once will have side-effects
logger.debug(response.member1 , response.member2)
return response
}
Is there a way to achieve this without using a 'return' keyword.
I am a newbie to scala so some (or most) of what I said could be wrong, and would be happy to be corrected.
Just reifying #Shadowlands answer.
def myfunc(argument: ArgType): ReturnType {
val response = dependency()
logger.debug(response.member1, response.member2)
response
}

How to write your own matcher in Circumflex?

As asked here, I need to run a Circumflex action only if a condition is met. Currently, I do it like this:
get("/") = requireLogin {
...
}
Now Circumflex supports Matchers, which can be put right within the get() specification:
get("/mail" & Host("localhost"))
How can I write my own matcher, so the above requireLogin gets closer to the Circumflex style? I wish to write something like this:
get("/" & IsLoggedIn) = {
...
}
Here is a simple implementation. All it takes is to define an object with the desired name, extending from AtomicMatcher (as this one implements add() etc) and implement the name and apply methods:
object IsLoggedIn extends AtomicMatcher {
def name = "IsLoggedIn"
def apply = {
// Not shown: figuring out whether user is logged in or not
if(loggedIn) {
Some(List(new MatchResult(name)))
}
else {
sendRedirect("/login")
throw new ResponseSentException;
}
}
}
If the user is logged in (ie. the action can be executed), you need to return a list of at least one MatchResult. If you don't want to execute the action, do something else and either return None or throw a ResponseSentException, which seems to be the preferred way.

; expected but <place your favourite keyword here> found

I'm trying to write a class for a scala project and I get this error in multiple places with keywords such as class, def, while.
It happens in places like this:
var continue = true
while (continue) {
[..]
}
And I'm sure the error is not there since when I isolate that code in another class it doesn't give me any error.
Could you please give me a rule of thumb for such errors? Where should I find them? are there some common syntactic errors elsewhere when this happens?
It sounds like you're using reserved keywords as variable names. "Continue", for instance, is a Java keyword.
You probably don't have parentheses or braces matched somewhere, and the compiler can't tell until it hits a structure that looks like the one you showed.
The other possibility is that Scala sometimes has trouble distinguishing between the end of a statement with a new one on the next line, and a multi-line statement. In that case, just drop the ; at the end of the first line and see if the compiler's happy. (This doesn't seem like it fits your case, as Scala should be able to tell that nothing should come after true, and that you're done assigning a variable.)
Can you let us know what this code is inside? Scala expects "expressions" i.e. things that resolve to a particular value/type. In the case of "var continue = true", this does not evaluate to a value, so it cannot be at the end of an expression (i.e. inside an if-expression or match-expression or function block).
i.e.
def foo() = {
var continue = true
while (continue) {
[..]
}
}
This is a problem, as the function block is an expression and needs to have an (ignored?) return value, i.e.
def foo() = {
var continue = true
while (continue) {
[..]
}
()
}
() => a value representing the "Unit" type.
I get this error when I forget to put an = sign after a function definition:
def function(val: String):Boolean {
// Some stuff
}