I have an Action with optional params that looks like this:
def editLink(storyId: Long, linkId: Long, thumbnail: Option[String], title: Option[String], description: Option[String], hidden: Option[Boolean]) = Action.async { ... }
This action is exposed as a JSRoute. I had assumed that providing null as a param to the javascript route from JavaScript would map to Scala's None, but that appears to be incorrect and, instead, it translates to a literal "null" String. How can I indicate that certain query parameters are None when using this action from JavaScript?
Javascript, this wonderful language has two keywords usually used to define the absence of something. null is one of them, undefined is another one. Knowing that when you omit a parameter in a function, it gets passed as undefined, I would imagine that this is what you should use for an optional parameter. As an example :
var f = function (param, optionalParam) {
console.log(optionalParam);
}
f(1, 2); // prints 2
f(1); // prints undefined
Related
implicit val formats = DefaultFormats
val p = each_rsvp.extract[RSVPData]
p.venue.getOrElse(default = None)
I have done the extraction using case classes. RSVPData is a case class defined as follows:
case class RSVPData(
venue: Option[VenueDetails] = None,
visibility: String,
response: String,
guests: Int,
member: MemberDetails,
rsvp_id: Long,
mtime: Long,
event: EventDetails,
group: GroupDetails
)
As shown above, parameter 'venue' is an optional field of type VenueDetails which is also a case class.
case class VenueDetails(venue_name: String, lon: Double, lat: Double, venue_id: Int)
When I do:
p.venue.getOrElse(Default=None)
I get the output as :
VenueDetails(Waller Creek Pub House,-97.73584,30.266438,24179503)
The above is returned as 'Product with Serializable'. How to extract data from VenueDetails case class separately as venue name, latitude, longitude, venue id, from this output .
I'm going to assume that p is an RSVPData item. Correct? (
When you use .getOrElse on an Option, you are attempting to provide a default value in the case where no value is defined (that is, when the value is None). In other words, getOrElse gives you an opportunity to provide default venue details when none are available, so that you can handle both cases in a consistent manner. In your case, this argument should be an instance of VenueDetails.
By passing None as the argument to getOrElse you're saying that you want None if the Option's value is None - which makes very little sense. Even worse, getOrElse now returns two types of value: a VenueDetails or None. So Scala determines the return type as those traits that are common to both of these types, which it has determined to be Product with Serializable. As a result, you can't treat the return value as a VenueDetails, and so you cannot access its members.
General rule of thumb: NEVER pass None to Option.getOrElse! ;-)
(As an aside, specifying the argument name in the call is unnecessary; p.venue.getOrElse(None) is simpler and equivalent to p.venue.getOrElse(default = None).)
So, now it depends upon what you're trying to do, which isn't clear from your question. I'll try to provide a few examples...
This first example is more imperative than functional. It attempts to print out details of the venue:
// Is the venue defined? (If None, then it's undefined.)
if (p.venue.isDefined) {
// Retrieve the defined details. Note that get throws an exception if p.venue is None.
// BTW, detail's type is inferred to be VenueDetails.
val details = p.venue.get
println(s"Venue: ${details.venue_name}, loc: (${details.lon}, ${details.lat}), id: ${details.venue_id}")
}
// Handle the case where the venue details are undefined.
else {
println("Venue details are unknown")
}
Here's a slightly more functional version:
val desc = p.venue.fold {
// This argument is evaluated only if p.venue is None.
"Venue details are unknown"
} {
// This argument is executed only if p.venue is defined (not None).
// Again, details is inferred to have type VenueDetails
details =>
s"Venue: ${details.venue_name}, loc: (${details.lon}, ${details.lat}), id: ${details.venue_id}"
}
println(desc)
This version uses a default VenueDetails instance for cases where the venue details are unknown:
// Default details for case where p.venue is None.
val defaultDetails = VenueDetails("Unknown", 0.0, 0.0, -1)
// Here, details will have type VenueDetails.
val details = p.venue.getOrElse(defaultDetails)
val desc = s"Venue: ${details.venue_name}, loc: (${details.lon}, ${details.lat}), id: ${details.venue_id}"
println(desc)
In this latter case, if p.venue is None, then the following will be printed:
Venue: Unknown, loc: (0.0, 0.0), id: -1
However, if p.venue is defined as per your example, then the following will be printed:
Venue: Waller Creek Pub House, loc: (-97.73584, 30.266438), id: 24179503
I hope this would work:
p.venue.map(_.venue_name).getOrElse(None)
From spray.io documentation page:
color
extract value of parameter “color” as String
color.?
extract optional value of parameter “color” as Option[String]
amount.as[Int]
extract value of parameter “amount” as Int, you need a matching Deserializer in scope for that to work (see also Unmarshalling)
So how can I parse optional Int value? Something like amount.?.as[Int] doesn't seem to work.
You can see the details here: https://github.com/spray/spray/blob/76ab89c25ce6d4ff2c4b286efcc92ee02ced6eff/spray-routing/src/main/scala/spray/routing/directives/NameReceptacle.scala
case class NameReceptacle[A](name: String) {
def as[B] = NameReceptacle[B](name)
def as[B](deserializer: FSOD[B]) = NameDeserializerReceptacle(name, deserializer)
def ? = as[Option[A]]
def ?[B](default: B) = NameDefaultReceptacle(name, default)
def ![B](requiredValue: B) = RequiredValueReceptacle(name, requiredValue)
}
The straightforward syntax would be
"amount".as[Option[Int]]
Unfortunately there is no syntactic sugar to create a NameRecaptable for an option type directly, but you can do it in two steps:
"amount".as[Int].as[Option[Int]]
? is an alias for NameRecaptable[A].as[Option[A]], so you can use the following code (note the postfix operator syntax):
"amount".as[Int]?
I ran across a function that looks like this:
def doSomethingQuestionable(config: someConfig, value: String)(default: => String) : String
What is interesting is the parameterless function that gets passed in as second argument group. In the code base, the method is only ever called with a config and two strings, the latter being some default value, but as a String, not a function. Within the code body of the method, default is passed on to a method that takes 3 string arguments. So the function "default" only resolves down to a string within the body of this method.
Is there any benefit, apart from a currying usage which does not happen with this method in the code base I am going through, of defining the method this way? Why not just define it with 3 string arguments in a single argument group?
What am I missing? Some compiler advantage here? Keep in mind, I am assuming that no currying will ever be done with this, since it is a large code base, and it is not currently done with this method.
The point is to have a potentially expensive default string that is only created when you need it. You write the code as if you're creating the string to pass in, but because it's a by-name parameter ('=> String') it will actually be turned into a function that will be transparently called whenever default is referenced in the doSomethingQuestionable method.
The reason to keep it separate is in case you do want a big block of code to create that string. If you never do and never will, it may as well be
def doSomethingQuestionable(config: someConfig, value: String, default: => String): String
If you do, however,
def doSomethingQuestionable(cfg, v){
// Oh boy, something went wrong
// First we need to check if we have a database accessible
...
// (Much pain ensues)
result
}
is way better than embedding the code block as one argument in a multi-argument parameter list.
This is a parameterless function returning a String:
() => String
Which is not what you have. This,
=> <WHATEVER>
is a parameter being passed by-name instead of by-value. For example:
=> String // A string being passed by-name
=> () => String // A parameterless function returning string being passed by-name
The difference between these modes is that, on by-value, the parameter is evaluated and the resulting value is passed, whereas on by-name, the parameter is passed "as is", and evaluated each time it is used.
For example:
var x = 0
def printValue(y: Int) = println(s"I got $y. Repeating: $y.")
def printName(y: => Int) = println(s"I got $y. Repeating: $y.")
printValue { x += 1; x } // I got 1. Repeating: 1.
printName { x += 1; x } // I got 2. Repeating: 3.
Now, as to why the method splits that into a second parameter, it's just a matter of syntactic pleasantness. Take the method foldLeft, for example, which is similarly defined. You can write something like this:
(1 to 10).foldLeft(0) { (acc, x) =>
println(s"Accumulator: $acc\tx: $x\tacc+x: ${acc+x}")
acc+x
}
If foldLeft was defined as a single parameter list, it would look like this:
(1 to 10).foldLeft(0, { (acc, x) =>
println(s"Accumulator: $acc\tx: $x\tacc+x: ${acc+x}")
acc+x
})
Not much different, granted, but worse looking. I mean, you don't write this thing below, do you?
if (x == y, {
println("Same thing")
}, {
println("Different thing"
})
In my Play 2 controller (Scala) I've a method that looks like the following.
start(id:String, keywords:Option[List[String]])
Basically I want to get pass a list of string as keywords where it's optional.
The following doesn't work and gives me a compile error.
GET /start start(id:String,options:Option[List[String]])
The error makes sense because even if this route compiled I'm not sure how I would pass a list of Strings in my GET URL.
I'm looking for suggestions to resolve this.
Since you're just using keywords, how about comma-separated values in the query string?
GET /start/:id controllers.Sample.start(id: String, options: Option[String])
/start/1233?options=key,word,test
Then in your controller convert to Option[List[String]]:
def start(id: String, options: Option[String]) = Action {
val opts: Option[List[String]] = options.map(_.split(',').filter(_.nonEmpty))
...
}
I've read a lot of code snippets in scala that make use of the symbol =>, but I've never really been able to comprehend it. I've tried to search in the internet, but couldn't find anything comprehensive. Any pointers/explanation about how the symbol is/can be used will be really helpful.
(More specifially, I also want to know how the operator comes into picture in function literals)
More than passing values/names, => is used to define a function literal, which is an alternate syntax used to define a function.
Example time. Let's say you have a function that takes in another function. The collections are full of them, but we'll pick filter. filter, when used on a collection (like a List), will take out any element that causes the function you provide to return false.
val people = List("Bill Nye", "Mister Rogers", "Mohandas Karamchand Gandhi", "Jesus", "Superman", "The newspaper guy")
// Let's only grab people who have short names (less than 10 characters)
val shortNamedPeople = people.filter(<a function>)
We could pass in an actual function from somewhere else (def isShortName(name: String): Boolean, perhaps), but it would be nicer to just place it right there. Alas, we can, with function literals.
val shortNamedPeople = people.filter( name => name.length < 10 )
What we did here is create a function that takes in a String (since people is of type List[String]), and returns a Boolean. Pretty cool, right?
This syntax is used in many contexts. Let's say you want to write a function that takes in another function. This other function should take in a String, and return an Int.
def myFunction(f: String => Int): Int = {
val myString = "Hello!"
f(myString)
}
// And let's use it. First way:
def anotherFunction(a: String): Int = {
a.length
}
myFunction(anotherFunction)
// Second way:
myFunction((a: String) => a.length)
That's what function literals are. Going back to by-name and by-value, there's a trick where you can force a parameter to not be evaluated until you want to. The classic example:
def logger(message: String) = {
if(loggingActivated) println(message)
}
This looks alright, but message is actually evaluated when logger is called. What if message takes a while to evaluate? For example, logger(veryLongProcess()), where veryLongProcess() returns a String. Whoops? Not really. We can use our knowledge about function literals to force veryLongProcess() not to be called until it is actually needed.
def logger(message: => String) = {
if(loggingActivated) println(message)
}
logger(veryLongProcess()) // Fixed!
logger is now taking in a function that takes no parameters (hence the naked => on the left side). You can still use it as before, but now, message is only evaluated when it's used (in the println).