I am really new to scala, and I am currently making my way through the tour (https://docs.scala-lang.org/tour/variances.html).
Now, looking at some library (akka-http), I stumbled across some code like this:
def fetchItem(itemId: Long): Future[Option[Item]] = Future {
orders.find(o => o.id == itemId)
}
And I don't quite understand the syntax, or more precisely, the = Future { part. As I learned, the syntax for methods is def [methodName]([Arguments])(:[returnType]) = [codeblock].
However the above seems to differ in that its having the Future in front of the "codeblock". Is this some kind of object instantiation? Because I could not find documentation about this syntax, I tried in my play code stuff like this:
{
val myCat:Cat = new Cat("first cat")
val myOtherCat:Cat = Cat { "second cat" }
val myThirdCat:Cat = MyObject.getSomeCat
}
...
object MyObject
{
def getSomeCat: Cat = Cat
{
"blabla"
}
}
And all of this works, in that it creates a new Cat object. So it seems like new Cat(args) is equivalent to Cat { args }.
But shouldn't def getSomeCat: Cat = Cat define a method with a code block, not the instantiate a new Cat object? I am confused.
I think there are a couple of things here:
1.
The [codeblock] in method syntax doesn't have to be enclosed in {}. If there's only one expression, it's allowed to omit them.
E.g.
def add(x: Int, y: Int) = x + y
or
def add(x: Int, y: Int) = Future { x + y }
2.
Each class can have its companion object define an apply() method, which can be invoked without explicitly saying "apply" (this is special Scala syntactic sugar). This allows us to construct instances of the class by going through the companion object, and since "apply" can be omitted, at first glance it looks like going through the class itself, just without the "new" keyword.
Without the object:
class Cat(s: String)
val myFirstCat: Cat = new Cat("first cat") // OK
val mySecondCat: Cat = Cat("second cat") // error
And now with the object:
class Cat(s: String)
object Cat {
def apply(s: String) = new Cat(s)
}
val myFirstCat: Cat = new Cat("first cat") // OK
val mySecondCat: Cat = Cat.apply("second cat") // OK
val myThirdCat: Cat = Cat("third cat") // OK (uses apply under the hood)
val myFourthCat: Cat = Cat { "fourth cat" } // OK as well
Note how fourth cat invocation works just fine with curly braces, because methods can be passed codeblocks (last evaluated value in the block will be passed, just like in functions).
3.
Case classes are another slightly "special" Scala construct in a sense that they give you convenience by automatically providing some stuff for you "behind the curtain", including an associated companion object with apply().
case class Cat(s: String)
val myFirstCat: Cat = new Cat("first cat") // OK
val mySecondCat: Cat = Cat.apply("second cat") // OK
val myThirdCat: Cat = Cat("third cat") // OK
What happens in your case with Future is number 2, identical to "fourth cat". Regarding your question about new Cat(args) being equivalent to Cat { args }, it's most likely situation number 3 - Cat is a case class. Either that, or its companion object explicitly defines the apply() method.
The short answer is Yes, that Future code is an object instanciation.
Your Cat class has a single String argument and can be created using Cat(<string>). If you want to compute a value for the string you can put it in a block using {} as you did in your example. This block can contain arbitrary code, and the value of the block will be the value of the last expression in the block which must be type String.
The Future[T] class has a single argument of type T and can be created using Future(T). You can pass an arbitrary block of code as before, as long as it returns a value of type T.
So creating a Future is just like creating any other object. The fetchItem code is just creating a Future object and returning it.
However there is a subtlety with Future in that the parameter is defined as a "call-by-name" parameter not the default "call-by-value" parameter. This means that it is not evaluated until it is used, and it is evaluated every time it is used. In the case of a Future the parameter is evaluated once at a later time and potentially on a different thread. If you use a block to compute the parameter then the whole block will be executed each time the parameter is used.
Scala has very powerful syntax and some useful shortcuts, but it can take a while to get used to it!
A typical method structure will look like:
case class Bar(name: String)
def foo(param: String): Bar = {
// code block.
}
However, Scala is quite flexible when its comes to method definition. One of flexibility is that if your method block contains single expression, then you can ignore curly braces { }.
def foo(param: String): Bar = {
Bar("This is Bar") //Block only contains single expression.
}
// Can be written as:
def foo(param: String): Bar = Bar("This is Bar")
// In case of multiple expressions:
def foo(param: String): Bar = {
println("Returning Bar...")
Bar("This is Bar")
}
def foo(param: String): Bar = println("Returning Bar...") Bar("This is Bar") //Fails
def foo(param: String): Bar = println("Returning Bar..."); Bar("This is Bar") //Fails
def foo(param: String): Bar = {println("Returning Bar..."); Bar("This is Bar")} // Works
Similarly, in your code, fetchItem contains only single expression - Future {orders.find(o => o.id == itemId)} that return a new Future (instance of Future) of Option[Item], therefore braces { } is optional. However, if you want you can write it inside braces as below:
def fetchItem(itemId: Long): Future[Option[Item]] = {
Future {
orders.find(o => o.id == itemId)
}
}
Similarly, if a method take only single parameter, you can use curly braces. i.e. you can invoke fetchItems as:
fetchItem(10)
fetchItem{10}
fetchItem{
10
}
So, why use curly braces { } instead of brackets ( )?
Because, you can provide multiple code blocks inside braces, and this situation is required when need to perform multiple computation and return a value as result of that computation. For example:
fetchItem{
val x = 2
val y = 3
val z = 2
(x + y)*z //final result is 10 which is passed as parameter.
}
// In addition, using curly braces will make your code more cleaner e.g. in case of higher ordered functions.
def test(id: String => Unit) = ???
test {
id => {
val result: List[String] = getDataById(x)
val updated = result.map(_.toUpperCase)
updated.mkString(",")
}
}
Now, coming to your case, when you invoke Future{...}, you are invoking apply(...) method of Scala future companion object that take function literal body: =>T as parameter and return a new Future.
//The below code can also be written as:
Future {
orders.find(o => o.id == itemId)
}
//Can be written as:
Future(orders.find(o => o.id == itemId))
Future.apply(orders.find(o => o.id == itemId))
// However, braces are not allowed with multiple parameter.
def foo(a:String, b:String) = ???
foo("1","2") //work
foo{"1", "2"} //won't work.
Related
Is it possible to run multiple extractors in one match statement?
object CoolStuff {
def unapply(thing: Thing): Option[SomeInfo] = ...
}
object NeatStuff {
def unapply(thing: Thing): Option[OtherInfo] = ...
}
// is there some syntax similar to this?
thing match {
case t # CoolStuff(someInfo) # NeatStuff(otherInfo) => process(someInfo, otherInfo)
case _ => // neither Cool nor Neat
}
The intent here being that there are two extractors, and I don't have to do something like this:
object CoolNeatStuff {
def unapply(thing: Thing): Option[(SomeInfo, OtherInfo)] = thing match {
case CoolStuff(someInfo) => thing match {
case NeatStuff(otherInfo) => Some(someInfo -> otherInfo)
case _ => None // Cool, but not Neat
case _ => None// neither Cool nor Neat
}
}
Can try
object ~ {
def unapply[T](that: T): Option[(T,T)] = Some(that -> that)
}
def too(t: Thing) = t match {
case CoolStuff(a) ~ NeatStuff(b) => ???
}
I've come up with a very similar solution, but I was a bit too slow, so I didn't post it as an answer. However, since #userunknown asks to explain how it works, I'll dump my similar code here anyway, and add a few comments. Maybe someone finds it a valuable addition to cchantep's minimalistic solution (it looks... calligraphic? for some reason, in a good sense).
So, here is my similar, aesthetically less pleasing proposal:
object && {
def unapply[A](a: A) = Some((a, a))
}
// added some definitions to make your question-code work
type Thing = String
type SomeInfo = String
type OtherInfo = String
object CoolStuff {
def unapply(thing: Thing): Option[SomeInfo] = Some(thing.toLowerCase)
}
object NeatStuff {
def unapply(thing: Thing): Option[OtherInfo] = Some(thing.toUpperCase)
}
def process(a: SomeInfo, b: OtherInfo) = s"[$a, $b]"
val res = "helloworld" match {
case CoolStuff(someInfo) && NeatStuff(otherInfo) =>
process(someInfo, otherInfo)
case _ =>
}
println(res)
This prints
[helloworld, HELLOWORLD]
The idea is that identifiers (in particular, && and ~ in cchantep's code) can be used as infix operators in patterns. Therefore, the match-case
case CoolStuff(someInfo) && NeatStuff(otherInfo) =>
will be desugared into
case &&(CoolStuff(someInfo), NeatStuff(otherInfo)) =>
and then the unapply method method of && will be invoked which simply duplicates its input.
In my code, the duplication is achieved by a straightforward Some((a, a)). In cchantep's code, it is done with fewer parentheses: Some(t -> t). The arrow -> comes from ArrowAssoc, which in turn is provided as an implicit conversion in Predef. This is just a quick way to create pairs, usually used in maps:
Map("hello" -> 42, "world" -> 58)
Another remark: notice that && can be used multiple times:
case Foo(a) && Bar(b) && Baz(c) => ...
So... I don't know whether it's an answer or an extended comment to cchantep's answer, but maybe someone finds it useful.
For those who might miss the details on how this magic actually works, just want to expand the answer by #cchantep anf #Andrey Tyukin (comment section does not allow me to do that).
Running scalac with -Xprint:parser option will give something along those lines (scalac 2.11.12)
def too(t: String) = t match {
case $tilde(CoolStuff((a # _)), NeatStuff((b # _))) => $qmark$qmark$qmark
}
This basically shows you the initial steps compiler does while parsing source into AST.
Important Note here is that the rules why compiler makes this transformation are described in Infix Operation Patterns and Extractor Patterns. In particular, this allows you to use any object as long as it has unapply method, like for example CoolStuff(a) AndAlso NeatStuff(b). In previous answers && and ~ were picked up as also possible but not the only available valid identifiers.
If running scalac with option -Xprint:patmat which is a special phase for translating pattern matching one can see something similar to this
def too(t: String): Nothing = {
case <synthetic> val x1: String = t;
case9(){
<synthetic> val o13: Option[(String, String)] = main.this.~.unapply[String](x1);
if (o13.isEmpty.unary_!)
{
<synthetic> val p3: String = o13.get._1;
<synthetic> val p4: String = o13.get._2;
{
<synthetic> val o12: Option[String] = main.this.CoolStuff.unapply(p3);
if (o12.isEmpty.unary_!)
{
<synthetic> val o11: Option[String] = main.this.NeatStuff.unapply(p4);
if (o11.isEmpty.unary_!)
matchEnd8(scala.this.Predef.???)
Here ~.unapply will be called on input parameter t which will produce Some((t,t)). The tuple values will be extracted into variables p3 and p4. Then, CoolStuff.unapply(p3) will be called and if the result is not None NeatStuff.unapply(p4) will be called and also checked if it is not empty. If both are not empty then according to Variable Patterns a and b will be bound to returned results inside corresponding Some.
I have the below code and in my findOrCreate() function, I'm getting an error saying Type mismatch found Unit, required Future[Customer]. The customerByPhone() function that is being called inside findOrCreate() also contains calls that are expecting Futures, which is why I'm using a fatmap. I don't know why the result of the flatmap is resulting in Unit. What am I doing wrong?
override def findOrCreate(phoneNumber: String, creationReason: String): Future[AvroCustomer] = {
//query for customer in db
val avroCustomer: Future[AvroCustomer] = customerByPhone(phoneNumber).flatMap(_ => createUserAndEvent(phoneNumber, creationReason, 1.0))
}
override def customerByPhone(phoneNumber: String): Future[AvroCustomer] = {
val query = Schema.Customers.byPhoneNumber(phoneNumber)
val dbAction: DBIO[Option[Schema.Customer]] = query.result.headOption
db.run(dbAction)
.map(_.map(AvroConverters.toAvroCustomer).orNull)
}
private def createUserAndEvent(phoneNumber: String, creationReason: String, version: Double): Future[AvroCustomer] = {
val query = Schema.Customers.byPhoneNumber(phoneNumber)
val dbAction: DBIO[Option[Schema.Customer]] = query.result.headOption
val data: JsValue = Json.obj(
"phone_number" -> phoneNumber,
"agent_number" -> "placeholder for agent number",
"creation_reason" -> creationReason
)
//empty for now
val metadata: JsValue = Json.obj()
//creates user
val avroCustomer: Future[AvroCustomer] = db.run(dbAction).map(_.map(AvroConverters.toAvroCustomer).orNull)
avroCustomer.onComplete({
case Success(null) => {
}
//creates event
case Success(customer) => {
val uuid: UUID = UUID.fromString(customer.id)
//create event
val event: Future[CustomerEvent] = db.run(Schema.CustomerEvents.create(
uuid,
"customer_creation",
version,
data,
metadata)
).map(AvroConverters.toAvroEvent)
}
case Failure(exception) => {
}
})
Future.successful(new AvroCustomer)
}
While Reactormonk basically answered this in the comments, I'm going to actually write an answer with some details. His comment that a val statement produces Unit is fundamentally correct, but I'm hoping some elaboration will make things more clear.
The key element that I see is that val is a declaration. Declarations in Scala are statements that don't produce useful values. Because of the functional nature of Scala, they do produce a value, but it is Unit and as there is only one instance of Unit, it doesn't carry any meaning.
The reason programmers new to Scala are often tempted to do something like this is that they don't think of blocks of code as statements and are often used to using return in other languages. So let's consider a simplified function here.
def foo(i: Int): Int = {
42 * i
}
I include a code block as I think that is key to this error, though it really isn't needed here. The value of a code block is simply the value of the last expression in the code block. This is why we don't have to specify return, but most programmers who are used to return are a bit uncomfortable with that naked expression at the end of a block. That is why it is tempting to throw in the val declaration.
def foo(i: Int): Int = {
val result = 42 * i // Error: type mismatch.
}
Of course, as was mentioned, but val results in Unit making this incorrect. You could add an extra line with just result, and that will compile, but it is overly verbose and non-idiomatic.
Scala supports the use of return to leave a method/function and give back a particular value, though the us is generally frowned upon. As such, the following code works.
def foo(i: Int): Int = {
return 42 * i
}
While you shouldn't use return in Scala code, I feel that imagining it being there can help with understanding what is wrong here. If you stick a return in front of the val you get code like the following.
def foo(i: Int): Int = {
return val result = 42 * i // Error: type mismatch.
}
At least to me, this code is clearly incorrect. The val is a declaration and as such it just doesn't work with a return. It takes some time to get used to the functional style of blocks as expressions. Until you get to that point, it might help just to act like there is a return at the end of methods without actually putting one there.
It is worth noting that, in the comments, jwvh claims that a declaration like this in C would return a value. That is false. Assignments in most C-family languages give back the value that was assigned, so a = 5 returns the value 5, but declarations don't, so int a = 5; does not give back anything and can't be used as an expression.
For example, if we have a method like
def find[A](xs: Seq[A], p: A => Boolean): Option[A] = {
xs.foreach(x => if (p(x)) return Some(x));
None;
}
(of course there is a library function for this, this is just an example). How does the execution escape foreach when the inner function returns?
Or in
def foo(x: AnyRef): String =
process(x match {
case (s: String) => s;
case _ => return "";
})
how does the execution avoid running process when return "" is issued?
The foo example depends on which of
def process(s: String): String
def process(s: => String): String
it is. I'm assuming the former, since you suggest process isn't run. This is just the way it always works when passing an argument--you do the argument-creation work first, then call the method. Since you run into a return, it's easy: you just call the appropriate return from bytecode while creating the argument*, and never go on to invoke the method. So it is just a local return.
The find example is a little more involved. Let's try a maximally simple example motivated by a foo which requires a nonlocal return:
class Nonlocal {
def pr(s: => String) = { println(s); "Printed" }
def foo(x: AnyRef): String = pr(x match {
case (s: String) => s;
case _ => return "";
})
}
The body of foo is equivalent to
import scala.runtime.NonLocalReturnControl
val temp = new AnyRef
try {
pr(x match {
case s: String => s
case _ => throw new NonLocalReturnControl(temp, "")
})
}
catch {
case nlrc: NonLocalReturnControl[_] if (nlrc.key eq temp) =>
nlrc.value.asInstanceOf[String]
}
The key things to notice is that a sentinel object is created so that these things can be arbitrarily nested without clobbering each other, and that NonLocalReturnControl carries the correct value back. Unsurprisingly, this isn't exactly cheap compared to just returning, say, an Int. But since it creates an exception without a stack trace (safe, because it can't escape: the catch block is guaranteed to catch it), it's not that bad--is about as bad as calling a trig function or summing an array with a few dozen entries.
Note also that pr only gets partly executed before the exception gets it. In this case, it doesn't print anything because the first thing it does is try to use s to fill in an actual string, but then it hits the exception which drops control back to foo. (So you get an empty string back from foo, but you don't print anything.)
* Actually, in bytecode it tends to be a jump to the end of the method, with the load/return there. Irrelevant conceptually, though.
In documentation of Option class written that following two examples are equivalent:
val name: Option[String] = request getParameter "name"
val upper = name map { _.trim } filter { _.length != 0 } map { _.toUpperCase }
println(upper getOrElse "")
and
val upper = for {
name <- request getParameter "name"
trimmed <- Some(name.trim)
upper <- Some(trimmed.toUpperCase) if trimmed.length != 0
} yield upper
println(upper getOrElse "")
But I don't understand how they can be equivalent: in first code block request getParameter "name" return instance of type Option[String], but in second code block statement name <- request getParameter "name" return instance of type String (I assumed that because next statement calls trim method on name variable (trim is not defined for Option[String])).
The conversion from for ... yield comprehension to map/flatMap method calls is done by the compiler. It's not required that the Option is an Iterable; the only thing necessary in this case is Option having map / flatMap methods:
flatMap if there are more -> calls after it in the same for block
map if it's the last one
We can create our own MyOption class like this:
case class MyOption[+T](value: T) {
def flatMap[A](f: T => MyOption[A]): MyOption[A] = f(value)
def map[A](f: T => A): MyOption[A] = MyOption(f(value))
override def toString = s"Some($value)"
}
Then:
val result = for {
a <- MyOption("one")
b <- MyOption("two")
} yield a + "," + b
println(result)
// prints: Some(one,two)
Option is an Iterable (there's an implicit option2Iterable method in Option companion object), that's why it can be used in someVar <- someOption clause. In fact, that arrow means "take elements from collection on the right".
So you're right, name in the 2nd example is a String.
In the 1st one you can see there are map and other Iterable methods used on Option. It is basically the same as for expression below, but calls methods directly, while for is just a syntax sugar and gets translated into the chain of method calls by the compiler.
Basically, I would like to be able to build a custom extractor without having to store it in a variable prior to using it.
This isn't a real example of how I would use it, it would more likely be used in the case of a regular expression or some other string pattern like construct, but hopefully it explains what I'm looking for:
def someExtractorBuilder(arg:Boolean) = new {
def unapply(s:String):Option[String] = if(arg) Some(s) else None
}
//I would like to be able to use something like this
val {someExtractorBuilder(true)}(result) = "test"
"test" match {case {someExtractorBuilder(true)}(result) => result }
//instead I would have to do this:
val customExtractor = someExtractorBuilder(true)
val customExtractor(result) = "test"
"test" match {case customExtractor(result) => result}
When just doing a single custom extractor it doesn't make much difference, but if you were building a large list of extractors for a case statement, it could make things more difficult to read by separating all of the extractors from their usage.
I expect that the answer is no you can't do this, but I thought I'd ask around first :D
Parameterising extractors would be cool, but we don't have the resources to implement them right now.
Nope.
8.1.7 Extractor Patterns
An extractor pattern x (p 1 , . . . ,
p n ) where n ≥ 0 is of the same
syntactic form as a constructor
pattern. However, instead of a case
class, the stable identifier x denotes
an object which has a member method
named unapply or unapplySeq that
matches the pattern.
One can customize extractors to certain extent using implicit parameters, like this:
object SomeExtractorBuilder {
def unapply(s: String)(implicit arg: Boolean): Option[String] = if (arg) Some(s) else None
}
implicit val arg: Boolean = true
"x" match {
case SomeExtractorBuilder(result) =>
result
}
Unfortunately this cannot be used when you want to use different variants in one match, as all case statements are in the same scope. Still, it can be useful sometimes.
Late but there is a scalac plugin in one of my lib providing syntax ~(extractorWith(param), bindings):
x match {
case ~(parametrizedExtractor(param)) =>
"no binding"
case ~(parametrizedExtractor(param), (a, b)) =>
s"extracted bindings: $a, $b"
}
https://github.com/cchantep/acolyte/blob/master/scalac-plugin/readme.md
Though what you are asking isn't directly possible,
it is possible to create an extractor returning a contaner that gets evaluated value in the if-part of the case evaluation. In the if part it is possible to provide parameters.
object DateExtractor {
def unapply(in: String): Option[DateExtractor] = Some(new DateExtractor(in));
}
class DateExtractor(input:String){
var value:LocalDate=null;
def apply():LocalDate = value;
def apply(format: String):Boolean={
val formater=DateTimeFormatter.ofPattern(format);
try{
val parsed=formater.parse(input, TemporalQueries.localDate());
value=parsed
true;
} catch {
case e:Throwable=>{
false
}
}
}
}
Usage:
object DateExtractorUsage{
def main(args: Array[String]): Unit = {
"2009-12-31" match {
case DateExtractor(ext) if(ext("dd-MM-yyyy"))=>{
println("Found dd-MM-yyyy date:"+ext())
}
case DateExtractor(ext) if(ext("yyyy-MM-dd"))=>{
println("Found yyyy-MM-dd date:"+ext())
}
case _=>{
println("Unable to parse date")
}
}
}
}
This pattern preserves the PartialFunction nature of the piece of code. I find this useful since I am quite a fan of the collect/collectFirst methods, which take a partial function as a parameter and typically does not leave room for precreating a set of extractors.