I have the below 2 definitions in Scala, Which gives me the same result. But It's bit different from each other.
def sum(f: Int => Int)(a: Int, b: Int): Int =
if (a > b) 0 else f(a) + sum(f)(a + 1, b) //> sum: (f: Int => Int)(a: Int, b: Int)Int
sum(x => x*x)(1,2) //> res3: Int = 5
The second one is
def sum(f: Int => Int,a: Int, b: Int): Int =
if (a > b) 0 else f(a) + sum(f,a + 1, b) //> sum2: (f: Int => Int, a: Int, b: Int)Int
sum(x => x*x,1,2) //> res4: Int = 5
The only different I see is sum(f: Int => Int,a: Int, b: Int)
and sum(f: Int => Int)(a: Int, b: Int)
. In the latter case the function parameter and the values parameters are separated.
What is this behavior. Is this really a same or is there a different between them ?
With respect to the way that you're using them they are pretty much identical. But the first version has some additional flexibility (and utility) in general.
For example
val g = sum(x => x*x) _ //g has type (Int, Int) => Int
println(g(2, 3)) //prints 13
This is called currying. You can do this with more than two argument lists, eg
def foo(b: Boolean)(i: Int)(s: String)(d: Double): Int = ...
val g = foo(true) _ //g has type Int => (String => (Double => Int))
val h = g(3) _ //h has type String => (Double => Int)
val r = h("asdf") _ //r has type Double => Int
The underscore can sometimes be left off depending on the context, eg
val r: Int => Double = foo(true)(3)("asdf")
Multiple argument lists are also used for implicit parameters, as well as at times when the Scala compiler needs some help with the type inferencing. When used together with call-by-name parameters they can also be handy for creating fake syntax or control structures via libraries, eg
def repeat(n: Int)(body: => Unit) {
var i = n
while (i > 0) { i -= 1; body }
}
var counter = 0
repeat(10) { //This method call (repeat) looks a bit like a part
println(s"Hello: $counter") //of the language due to call-by-name argument,
counter += 1 //multiple parameter lists, use of curly braces, etc.
}
results in
Hello: 1 Hello: 2 . . . Hello 9
Yes, they are the same. You can use multiple parameter blocks for several reasons, none of which apply here:
To help type inference with generic methods (eg if you have def foo[A](a: A, f: A => A)
and call foo(1, _ + 1)
you might expect the compiler to understand that A
is Int
. But it can't do that before determining the type of _ + 1
. If you use def foo[A](a: A)(f: A => A)
instead, it'll work.
To use previous arguments in default values. Eg def foo(x: Int, y: Int = x)
doesn't compile, def foo(x: Int)(y: Int = x)
does.
A function argument by itself can be written in braces without parentheses:
def sum(a: Int, b: Int)(f: Int => Int): Int sum(1, 2) { x => x*x }
The last block can contain implicit parameters .
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.