1 and 2 are the same, and this is eta-expand , which means that a function is transformed from just a function as part of the language to the real object of a certain FunctionN class:
scala> def f(a: Int) = a f: (a: Int)Int scala> f.apply(1) <console>:9: error: missing arguments for method f; follow this method with `_' if you want to treat it as a partially applied function f.apply(1) ^ scala> f _ res1: Int => Int = <function1> scala> (f _).apply(1) res2: Int = 1
In your example, this does not work, since handler(resource) is an expression that returns a Byte => T object object (since handler is a FileInputStream => Byte => T object function, and you partially applied it), so scala cannot do eta extensions for expressions (only for values and methods).
4 is partially used as a side effect of supporting scala curry functions ( curried i means the ability to measure parameters one by one).
3 is clearly explicitly partially applied .
Note that in all three examples, your handler: FileInputStream => Byte => T function handler: FileInputStream => Byte => T is an object (therefore, it is already extended) if you are trying to do the same using methods with several parameters (which are not yet expanded to a curry function) - you get opposite results for 1 & 2 & 4:
scala> def f(a: Int)(b: Int) = a
Thus, a partial application also makes the eta extension for you. You can also think of the eta extension as a (not exact) function with 0 partially applicable arguments, so these are pretty close terms, since partially applied functions are always objects in scala (in haskell it is a first-class function ), because you always need partially the applied function is first-class (for example, an object or an fc function) to apply it after an eta extension.
5 . scala can do eta extensions for the values themselves, since they can be considered as compile-time functions with 0 parameters (which is why you see () => ... ). It can extend any value for a function object:
scala> val k = 5 k: Int = 5 scala> val kk = k _ kk: () => Int = <function0> scala> val kkk = kk _ kkk: () => () => Int = <function0> scala>
In your example, value is another object object. In addition, (Int, Int) => Int does not fully work in curry (the function takes some values according to some estimates), but scala can also perform automatic partial application for such purposes. To make it fully charged:
scala> def f(a: Int, b: Int) = a f: (a: Int, b: Int)Int scala> (f _).curried res23: Int => (Int => Int) = <function1> scala> def f(a: Int, b: Int)(z: Int) = a f: (a: Int, b: Int)(z: Int)Int scala> (f _).curried res22: Int => (Int => (Int => Int)) = <function1>
This process is actually called currying.
Another way to make it in curry is to use tuples. It's not as clean as currying actually removes tuples, but scala Tuple is just a class and not a tuple in the parameter list: (Int, Int) => Int - the input is not a tuple in scala terminology, but in ((Int, Int)) => Int input tuple (regardless of what FP-perspecive is, a tuple of objects in the first case and a tuple of one object in the second). An example of pseudo-tuping:
scala> def f(a: Int, b: Int) = a f: (a: Int, b: Int)Int scala> (f _).tupled res24: ((Int, Int)) => Int = <function1>
5 vs 1 & 2 As you have already seen, you cannot apply the eta extension to an expression, only the / values / vars methods:
scala> 5 _ <console>:8: error: _ must follow method; cannot follow Int(5) 5 _ ^ scala> val (a, b) = (5, 5) scala> (a + b) _ <console>:10: error: _ must follow method; cannot follow Int (a + b) _ ^
You see the “method” required in the error message, but scala aims to handle methods / values / vars (when they are members of a class / object) in the same way (at least partially) with UAP support.
6 This is the eta extension that returns Function0 by default:
scala> val a = println _ a: () => Unit = <function0>
Here you can expect function1, but println overloaded, and the eta extension mechanism selects the smallest signature. When another type is expected (for example, in Function1 in foreach ) - it can choose another:
scala> val a: String => Unit = println _ a: String => Unit = <function1>
As I said, you can consider an object function as a function partially applied with 0 arguments (which includes an eta extension, if necessary), so there is a source of confusion with another answer (I would choose the best example there).
As stated in PS2, this extension can be applied automatically:
scala> List(1,2) foreach println 1 2
About println _ +"#" - it works because any class (including Function1 ) in scala has implicit def + (s: String) (therefore, Int does not work here) defined in Predef (see SI-194 ):
scala> println _ res50: () => Unit = <function0> scala> println _ + "#" res51: String = <function0>
All other parameters do not work due to 5 vs 1 & 2 , in fact, scala cannot even parse a line after a one-parameter function:
scala> println "#" <console>:1: error: ';' expected but string literal found. println "#" ^
You must specify the host object to fix it, since scala expects something like "obj method param" (but this is an experimental function, and sometimes you need to insert a few empty lines or ";" to make it work):
scala> Predef println "aaa" aaa
PS About C ++ reference / pointer. A function does not matter as a compile-time structure; therefore, the compiler simply creates a value for it; this process is called eta-expand (or this abstraction for pure functionality). This value can be part of a pointer (an object with a link to it) or just a reference to it - it does not matter. The fact is that here the function moves from compilation (method) to the runtime (fc-function), so it "comes to life".
PS2. Sometimes scala does this extension automatically (for example, here ) when a partially applied method with several parameters is explicitly passed as a parameter.
PSN You can find more information about underscores in @Daniel C. Sobral's answer about scala prefixes.