4

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!

Duc Le
  • 61
  • 7
  • https://docs.scala-lang.org/tour/multiple-parameter-lists.html – Seth Tisue Aug 11 '22 at 17:36
  • Does this answer your question? [What's the difference between multiple parameters lists and multiple parameters per list in Scala?](https://stackoverflow.com/questions/6803211/whats-the-difference-between-multiple-parameters-lists-and-multiple-parameters) – Seth Tisue Aug 11 '22 at 17:37

2 Answers2

5

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)
Dylan
  • 13,645
  • 3
  • 40
  • 67
-2

This is called currying, and it means that the function returns another function that takes one argument.

Ron Adin
  • 49
  • 8