1

I'm a Scala beginner. Can someone explain me what is the difference (except syntax) between these two lines of code (though they return the same result)? I wrote them practicing literal functions and try to find out if there is anything up 'behind the scene'?

val literal1 = (fn: Int => Int, x: Int) => fn(x)

val literal2 = (fn: Int => Int) => (x: Int) => fn(x)          

I see that there is a possibility of passing arguments into functions in different ways. But does it really matter which way I choose (except of currying case)?

literal1(p => p + 1, 2) /*3*/

literal2(p => p + 1)(2) /*3*/
Dmytro Mitin
  • 48,194
  • 3
  • 28
  • 66
vonBluten
  • 11
  • 2
  • 2
    The first one is a function of two arguments that returns another function of one argument; which returns an int, and the second one is a function of three arguments that returns an int. - You rarely want the overhead of currying without a good reason. – Luis Miguel Mejía Suárez Jan 13 '23 at 22:00
  • 3
    https://stackoverflow.com/questions/4915027/two-ways-of-currying-in-scala-whats-the-use-case-for-each https://stackoverflow.com/questions/69489355/whats-the-purpose-of-currying-given-other-alternatives-to-return-a-function-in https://stackoverflow.com/questions/57089139/currying-functions-in-scala https://stackoverflow.com/questions/41644168/understanding-currying-in-scala https://stackoverflow.com/questions/18398574/curried-function-in-scala – Dmytro Mitin Jan 14 '23 at 03:02

1 Answers1

0

These two values have different types:

val literal1: (Int => Int, Int) => Int = <function>
val literal2: (Int => Int) => (Int => Int) = <function>

In other words, literal1 is a function that takes two arguments—a function that takes an Int and returns an Int, and an Int—and returns an Int.

On the other hand, literal2 is a function that takes one argument—a function that takes an Int and returns an Int, and returns a function that takes an Int and returns an Int.

Other than the different calling convention, the second form allows you to easily partially apply the first parameter, returning a function that takes an Int and returns an Int:

val doubler = literal2(_ * 2) // val doubler: Int => Int = <function>

doubler(2) // val res0: Int = 4
doubler(5) // val res1: Int = 10

Doing the same with the first form requires very slightly more complex syntax:

val doubler = literal1(_ * 2, _)

doubler(2)
doubler(5)

The first form can be transformed automatically to the second using its curried method:

val literal3 = literal1.curried // val literal3: (Int => Int) => (Int => Int) = scala.Function2<function>

literal3(_ * 3)(6) // val res2: Int = 18

Note that it is conventional in Scala for functions and methods that take a single function argument to specify it as the final argument in a curried format, as this allows for a convenient syntax for a multi-line lambda:

val literal4 = (x: Int) => (fn: Int => Int) => fn(x)

literal4(25) { x =>
  val mod = x % 2
  if (mod == 0) println("even")
  else println("odd")
  mod
}

Output:

val literal4: Int => ((Int => Int) => Int) = <function>

odd
val res3: Int = 1
Tim Moore
  • 8,958
  • 2
  • 23
  • 34