【发布时间】:2015-01-01 16:32:51
【问题描述】:
这些下划线用法与这些代码有什么区别和术语名称:(参见handler(resource)部分)
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))
}
我得到编译错误:
Error:(55, 29) _ must follow method; cannot follow Byte => T
val hh = handler(resource)_
^
什么意思?
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...
// ...
结果与否相同。 1、我得到:_ must follow method编译错误。
我读到这是因为下划线用于将方法转换为函数(ETA 扩展),但我也看到相同的下划线用于 Partial Applied Function 没有问题,例如:
val sum = (x: Int, y: Int) => x + y
val sum2 = sum _
在这种情况下没有错误。
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()
}
}
//...
这个很好用。如果我没记错的话,这种情况下的下划线叫做ETA 扩展,对吗?但我也从this Q/A 读到,这种下划线用于部分应用函数。在同一页面中,也有人说这是一个占位符语法。那么哪一个是正确的呢?
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()
}
}
//...
这个不使用下划线,但它也可以正常工作,就像没有一样。 3.我对这个案子的疑问,和no有什么区别。 3?我应该使用否。 4比没有。 3? no中的下划线是否多余。 3?
对不起,这里有很多问题,但是下划线的事情真的很混乱。
不知何故,我认为 Scala 中下划线的复杂性与 C/C++ 中指针和引用 (*/&/&&) 的复杂性相匹配。
更新:
5.
我又发现了一些关于下划线的有趣之处:
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
你能告诉我sum4 发生了什么吗?为什么sum3 _的结果有函数类型:() => (Int, Int) => Int?
6.
List(1, 2, 3) foreach println _
根据this answer,这是部分应用函数。好的,我可以看到下划线之前的空格有点棘手。它实际上是一样的:
List(1, 2, 3).foreach(println(_))
所以这确实是部分应用函数。
但如果我这样做:
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 "#"+_)
^
新手通常会认为这种情况下的下划线是占位符,但我相信不是,不是吗?
【问题讨论】:
-
ETA 扩展是您的飞机真的要晚点的时候。
-
@som-snytt 两年后我得到了这个笑话 :)))
标签: scala functional-programming