Why does a partial function applied to two functions that perform the same function defined in two different ways return a different result?

I can define the following two functions:

def add(a: Int, b: Int, c: Int) = a + b + c 

This leads to

 add: (a: Int, b: Int, c: Int)Int 

and

 val add2 = (a: Int, b: Int, c: Int) => a + b + c 

This leads to

 add2: (Int, Int, Int) => Int = <function3> 

Both of these functions are the same, but defined differently, which I don’t understand if I continue and define a partially applicable function as follows:

 def a = add _ 

The result is

 a: (Int, Int, Int) => Int = <function3> 

as expected, a function that takes 3 parameters and returns Int, but if I do

 def a2 = add2 _ 

The result is

 a2: () => (Int, Int, Int) => Int = <function0> 

which seems to be a function that takes no parameters and returns a function that takes 3 parameters of Int and returns Int. Why is this happening? Can someone explain what is happening?

thanks

+7
source share
3 answers

This is a strange side effect of Scala, which actually has no (custom) fields, but instead has accessors (getters) for everything. Note:

 scala> val i = 1 i: Int = 1 scala> i _ res0: () => Int = <function0> 

The reason is that i is actually an accessor ( def i: Int ) in the base (hidden, inaccessible) field. Since this is just a method, _ converts it to a function. The accessory does not accept any arguments, so you have a function that does not accept any parameters.

+9
source

Scala has both functions and methods; they are not exactly the same thing.

 def add(a: Int, b: Int, c: Int) = a + b + c 

Defines a method (not a function !!).

 val add2 = (a: Int, b: Int, c: Int) => a + b + c 

What is the function add2 assigned (not the method !!).

The can not method will be the final value, and the function can:

 scala> add <console>:9: error: missing arguments for method add; follow this method with `_' if you want to treat it as a partially applied function add ^ scala> add2 res1: (Int, Int, Int) => Int = <function3> scala> val a = add <console>:8: error: missing arguments for method add; follow this method with `_' if you want to treat it as a partially applied function val a = add ^ scala> val a2 = add2 a2: (Int, Int, Int) => Int = <function3> 

Writing an underscore after the method name can explicitly convert the method to a function:

 scala> add _ res2: (Int, Int, Int) => Int = <function3> 

But if you write an underscore after the value, it is converted to a function that does not accept an argument with the return type:

 scala> val s = "" s: String = "" scala> val i = 1 i: Int = 1 scala> s _ res3: () => String = <function0> scala> i _ res4: () => Int = <function0> 

So, if the value itself is a function, writing an underscore after it receives a new function that does not accept an argument with the return type of the function:

 scala> add2 _ res5: () => (Int, Int, Int) => Int = <function0> 
+2
source

The effect is clearly described in the Rex Kerr answer , but you should notice that add2 is a value that already represents a partially applied function, for example. delegate. For a demonstration, you can compare the expression types add1 _ and add2 .

 scala> def getManifest[T](x:T)(implicit m:scala.reflect.Manifest[T]) = m getManifest: [T](x: T)(implicit m: scala.reflect.Manifest[T])scala.reflect.Manifest[T] scala> getManifest(add1 _) == getManifest(add2) res14: Boolean = true 
+1
source

All Articles