I got this piece of code from https://index.scala-lang.org/playframework/play-json that I don't fully understand:
implicit val locationReads: Reads[Location] = (
(JsPath \ "lat").read[Double](min(-90.0) keepAnd max(90.0)) and
(JsPath \ "long").read[Double](min(-180.0) keepAnd max(180.0))
)(Location.apply _)
What does (...)(...)
mean? I took a look at the Scala syntax cheat sheet but still cannot figure what it is. Thank you in advance!
CodePudding user response:
This is called currying, and it means that the function returns another function that takes one argument.
CodePudding user response:
Without syntax sugar, what you have is:
(JsPath \ "lat").read[Double](min(-90.0) keepAnd max(90.0))
.and( (JsPath \ "long").read[Double](min(-180.0) keepAnd max(180.0)) )
.apply(Location.apply _)
The parentheses around the (... and ...)
in your post are just like the parentheses in an expression like (1 2) / 3
. They were used so the and
method could be called like an operator and then call a method on the result of that and
method. Nothing really special there.
The parentheses around Location.apply _
are because you are passing Location.apply _
as an argument to a function. You are technically calling the (... and ...)
object's apply
method, and omitting the word "apply" thanks to a Scala syntax sugar.
In scala, objects with an apply
method can be treated as functions thanks to the syntax sugar, i.e. the following two statements are equivalent:
foo.apply(1)
foo(1) // equivalent
Note that this is not "currying" as the other answer states.
Currying is a way to represent a function with multiple arguments as a series of "functions which return functions", e.g.
def myFunc(a: Int, b: Int, c: Int) = a b c
val sum = myFunc(1, 2, 3)
def myCurriedFunc(a: Int)(b: Int)(c: Int) = a b c
val sum = myCurriedFunc(1)(2)(3)
val addOneAndTwo = myCurriedFunc(1)(2)
val sumAgain = addOneAndTwo(3)