Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
这些scala';s方法_Scala_Functional Programming - Fatal编程技术网

这些scala';s方法

这些scala';s方法,scala,functional-programming,Scala,Functional Programming,这些代码的下划线用法和术语名称有什么区别:(请参阅处理程序(参考资料)部分) 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 {

这些代码的下划线用法和术语名称有什么区别:(请参阅
处理程序(参考资料)
部分)

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))
}
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...
// ...
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()
    }
}

//...
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()
    }
}

//...
List(1, 2, 3) foreach println _
我得到编译错误:

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()
    }
}

val bs = new Array[Byte](4)

readFile(new File("scala.txt")) {
    input => b: Byte => println("Read: " + (input.read(bs) + b))
}
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...
// ...
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()
    }
}

//...
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()
    }
}

//...
List(1, 2, 3) foreach println _
结果与1号相同,我得到:
\u必须遵循方法
编译错误

我读到这篇文章是因为下划线用于将方法转换为函数(ETA扩展),但我也看到相同的下划线用于部分应用函数,没有问题,例如:

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()
    }
}

val bs = new Array[Byte](4)

readFile(new File("scala.txt")) {
    input => b: Byte => println("Read: " + (input.read(bs) + b))
}
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...
// ...
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()
    }
}

//...
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()
    }
}

//...
List(1, 2, 3) foreach println _
这个很好用。如果我没有错的话,本例中的下划线称为“ETA扩展”,对吗?但我也从中读到,这种下划线用于部分应用函数。在同一页中,有人还说这是一种占位符语法。那么哪一个是正确的呢

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()
    }
}

val bs = new Array[Byte](4)

readFile(new File("scala.txt")) {
    input => b: Byte => println("Read: " + (input.read(bs) + b))
}
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...
// ...
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()
    }
}

//...
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()
    }
}

//...
List(1, 2, 3) foreach println _
这一个不使用下划线,但它的效果也很好,就像3号一样。我的问题是,3号有什么不同?我应该用4号而不是3号吗?3号的下划线是多余的吗

很抱歉这里有很多问题,但是下划线的东西真的很混乱

不知何故,我认为Scala中下划线的复杂性与C/C++中指针和引用(*/&/&&&&)的复杂性相匹配

更新:

5.

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))
}
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...
// ...
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()
    }
}

//...
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()
    }
}

//...
List(1, 2, 3) foreach println _
我又发现了下划线的有趣之处:

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
根据,这是部分应用的函数。好的,我可以看到下划线前的空格有点棘手。它实际上与:

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 "#"+_)
                                     ^
scala>List(1,2,3).foreach(println+1)//1
:8:错误:类型不匹配;
发现:Int(1)
必需:字符串
列表(1,2,3).foreach(println+1)
^
scala>List(1,2,3).foreach(println+“#”)//#2什么也没打印出来(为什么?)
scala>List(1,2,3).foreach(println 1+)/#3
:1:错误:“)”应为,但找到整数文本。
列表(1,2,3).foreach(println 1+)
^
scala>List(1,2,3).foreach(println“#”+#)/#4
:1:错误:“)”应为,但找到字符串文字。
列表(1,2,3).foreach(println“#”+)
^

新手通常会认为下划线在这种情况下是占位符,但我相信它不是,不是吗?

1和2-都是一样的,这意味着函数正在从作为语言一部分的函数转换为某些
函数的真实对象n
类:

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
所以,如果需要,部分应用程序也会为您进行eta扩展。您可能还认为eta扩展是(不确切地说)具有0个部分应用参数的函数,因此这是非常接近的术语,因为部分应用函数始终是scala中的对象(在haskell中是),因为在eta扩展之后,您始终需要部分应用函数(如object或f-c-function)来应用它

5。Scala可以对值本身进行eta扩展,因为它们可能被视为具有0个参数的编译时函数(这就是为什么您会看到
()=>…
)。它可以将任何值扩展到函数对象:

scala> val k = 5
k: Int = 5

scala> val kk = k _
kk: () => Int = <function0>

scala> val kkk = kk _
kkk: () => () => Int = <function0>

scala> 
这个过程实际上叫做咖喱

另一种方法是使用元组。它并不像currying实际删除元组那样纯粹,但scala的元组只是一个类,而不是参数列表中的元组:
(Int,Int)=>Int
-input在scala的术语中不是元组,但在
((Int,Int))=>Int
中,input是元组(不管从FP的角度来看,第一种情况是to对象的元组,第二种情况是一个对象的元组)。伪元组示例:

 scala> def f(a: Int, b: Int) = a
 f: (a: Int, b: Int)Int

 scala> (f _).tupled
 res24: ((Int, Int)) => Int = <function1>

正如我所说的,您可以将函数对象视为部分应用0个参数的函数(如果需要的话,它包括ETA扩展),因此这是与另一个参数混淆的根源(我会在那里选择更好的例子)。 正如我在p.S.2中所说,此扩展可自动应用:

scala> List(1,2) foreach println
1
2
关于
println+“#”
-它之所以有效,是因为scala中的任何类(包括
Function1
)都有Predef中定义的
隐式def+(s:String)
(这就是为什么
Int
在这里不起作用的原因)(请参阅):

关于C++的引用/指针。函数没有编译时结构的值,编译器只是为它创建一个值,这个过程称为ETA扩展(或者纯函数的ETA抽象)。这个值可以是指针的一部分(引用它的对象)。重要的是函数从编译(方法)移动到运行时(f-c-function),所以它“变得活跃”

p.S.2.当部分应用的多参数列表方法作为参数显式传递时,scala有时会自动(像)进行eta扩展


注意:你可以在@Daniel C.Sobral中找到关于scala标点符号的下划线的其他信息。

我的意思是
handler:FileInputStream=>Byte=>T
是一个对象(所以它已经扩展了),例如,如果你有类似
f(a:FileInputStream)(b:Byte)的方法T
-在传递到
readFile
之前,必须先将其扩展到函数对象:
readFile(file)(f)
,但实际上scala可以这样做(eta扩展)自动
readFile
不是一个函数-它是一种方法,只有在进行eta扩展时,它才能成为函数。但你是对的,我所说的curry实际上是指curry函数,所以稍微更正了一下我的答案。是的,因为
sum4
在那里被解释为只是值(不是函数),所以简单地说
()=>
是由
添加到前面的