What is the difference and the term name between these underscore usage from these codes: (see the handler(resource)
part)
1.
def readFile[T](f: File)(handler: FileInputStream => Byte => T): T = {
val resource = new java.io.FileInputStream(f)
try {
val hh = handler(resource)_
hh(2)
} finally {
resource.close()
}
}
val bs = new Array[Byte](4)
readFile(new File("scala.txt")) {
input => b: Byte => println("Read: " + (input.read(bs) + b))
}
I got compile error:
Error:(55, 29) _ must follow method; cannot follow Byte => T
val hh = handler(resource)_
^
What does it mean?
2.
def readFile[T](f: File)(handler: FileInputStream => Byte => T): T = {
val resource = new java.io.FileInputStream(f)
try {
val hh = handler(resource) _
hh(2)
} finally {
resource.close()
}
}
// Lower parts are same, so removed for brevity...
// ...
The result is same as no. 1, I got: _ must follow method
compile error.
I read this is because the underscore is used to convert method to function (ETA Expansion), but I also seen the same underscore is used for Partial Applied Function without problem, for example:
val sum = (x: Int, y: Int) => x + y
val sum2 = sum _
No error in this case.
3.
def readFile[T](f: File)(handler: FileInputStream => Byte => T): T = {
val resource = new java.io.FileInputStream(f)
try {
val hh = handler(resource)(_)
hh(2)
} finally {
resource.close()
}
}
//...
This one works fine. If I'm not wrong, the underscore in this case is called ETA Expansion, is that correct? But I also read from this Q/A, this kind of underscore is for Partial Applied Function. In same page, someone also said this is a Placeholder syntax. So which one is the correct one?
4.
def readFile[T](f: File)(handler: FileInputStream => Byte => T): T = {
val resource = new java.io.FileInputStream(f)
try {
val hh = handler(resource)
hh(2)
} finally {
resource.close()
}
}
//...
This one doesn't use underscore but it works fine too just like no. 3. My question for this case, what is the difference with no. 3? Should I use no. 4 than no. 3? Is the underscore redundant in no. 3?
Sorry for a lot of questions here, but that underscore thing is really confusing.
Somehow I thought the complexity of underscore in Scala matches the complexity of pointer and reference (*/&/&&) in C/C++.
UPDATE:
5.
I found something interesting again about the underscore:
scala> def sum(x: Int, y: Int) = x + y // sum is a method because of def
sum: (x: Int, y: Int)Int
scala> val sum2 = sum _ // sum2 is explicit ETA expanded function from sum
sum2: (Int, Int) => Int = <function2>
scala> sum2(2,3) // testing
res0: Int = 5
scala> val sum3 = (x: Int, y: Int) => x + y // sum3 is a function object
sum3: (Int, Int) => Int = <function2>
scala> val sum4 = sum3 _ // what happpened here?
sum4: () => (Int, Int) => Int = <function0>
scala> sum4()(2,3)
res2: Int = 5
Could you tell me what happened to sum4
? Why the result of sum3 _
has function type: () => (Int, Int) => Int
?
6.
List(1, 2, 3) foreach println _
According to this answer, this is Partially applied functions. Ok, I can see that the space before underscore is kinda tricky. It is actually same as:
List(1, 2, 3).foreach(println(_))
So this is indeed Partially applied function.
But if I did this:
scala> List(1, 2, 3).foreach(println _+1) //#1
<console>:8: error: type mismatch;
found : Int(1)
required: String
List(1, 2, 3).foreach(println _+1)
^
scala> List(1, 2, 3).foreach(println _+"#") //#2 printed out nothing (why?)
scala> List(1, 2, 3).foreach(println 1+_) //#3
<console>:1: error: ')' expected but integer literal found.
List(1, 2, 3).foreach(println 1+_)
^
scala> List(1, 2, 3).foreach(println "#"+_) //#4
<console>:1: error: ')' expected but string literal found.
List(1, 2, 3).foreach(println "#"+_)
^
Newcomer usually will think the underscore in this case as placeholder, but I believe it isn't, isn't it?