在 Scala 中编写 read-while 循环的正确方法是什么?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3011106/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-22 02:12:37  来源:igfitidea点击:

What is the proper way to code a read-while loop in Scala?

scalainputstreamio

提问by ARKBAN

What is the "proper" of writing the standard read-while loop in Scala? By proper I mean written in a Scala-like way as opposed to a Java-like way.

在 Scala 中编写标准的 read-while 循环的“正确”是什么?正确的意思是用类似于 Scala 的方式而不是类似于 Java 的方式编写。

Here is the code I have in Java:

这是我在Java中的代码:

MessageDigest md = MessageDigest.getInstance( "MD5" );
InputStream input = new FileInputStream( "file" );
byte[] buffer = new byte[1024];
int readLen;
while( ( readLen = input.read( buffer ) ) != -1 )
    md.update( buffer, 0, readLen );
return md.digest();

Here is the code I have in Scala:

这是我在 Scala 中的代码:

val md = MessageDigest.getInstance( hashInfo.algorithm )
val input = new FileInputStream( "file" )
val buffer = new Array[ Byte ]( 1024 )
var readLen = 0
while( readLen != -1 )
{
    readLen = input.read( buffer )
    if( readLen != -1 )
        md.update( buffer, 0, readLen )
}
md.digest

The Scala code is correct and works, but feels very un-Scala-ish. For one it is a literal translation of the Java code, taking advantage of none of the advantages of Scala. Further it is actually longer than the Java code! I really feel like I'm missing something, but I can't figure out what.

Scala 代码是正确且有效的,但感觉非常不符合 Scala 风格。一方面,它是 Java 代码的字面翻译,没有利用 Scala 的任何优势。此外,它实际上比 Java 代码还要长!我真的觉得我错过了一些东西,但我无法弄清楚是什么。

I'm fairly new to Scala, and so I'm asking the question to avoid falling into the pitfall of writing Java-style code in Scala. I'm more interested in the Scala way to solve this kind of problem than in any specific helper method that might be provided by the Scala API to hash a file.

我对 Scala 相当陌生,所以我提出这个问题是为了避免陷入在 Scala 中编写 Java 风格代码的陷阱。我对 Scala 解决此类问题的方法更感兴趣,而不是 Scala API 可能提供的任何特定帮助方法来散列文件。

(I apologize in advance for my ad hoc Scala adjectives throughout this question.)

(我提前为我在整个问题中的临时 Scala 形容词道歉。)

回答by Sandor Murakozi

Based on Rex's post that he mentioned:

根据他提到的 Rex 的帖子:

Stream.continually(input.read(buffer)).takeWhile(_ != -1).foreach(md.update(buffer, 0, _))

You should replace the var readLen + while {...} lines with it, it produces the same result.

您应该用它替换 var readLen + while {...} 行,它会产生相同的结果。

As Rex mentioned, it works with scala 2.8.

正如 Rex 所提到的,它适用于 Scala 2.8。

回答by michael.kebe

What Rex Kerr suggests in his comment is the following:

Rex Kerr 在他的评论中建议如下:

val md = MessageDigest.getInstance("MD5")
val input = new FileInputStream("foo.txt")
val buffer = new Array[ Byte ]( 1024 )
Stream.continually(input.read(buffer))
  .takeWhile(_ != -1)
  .foreach(md.update(buffer, 0, _))
md.digest

The key is the Stream.continually. It gets an expression which is evaluated continually, creating an infinite Streamof the evaluated expression. The takeWhileis the translation from the while-condition. The foreachis the body of the while-loop.

关键是Stream.continually。它得到一个连续Stream求值的表达式,创建一个无限的求值表达式。ThetakeWhilewhile-condition的翻译。该foreach是身体while-loop。

回答by Ant Kutschera

What about a curried function? You 11 lines of Scala code become:

咖喱函数呢?你的 11 行 Scala 代码变成了:

val md = MessageDigest.getInstance(hashInfo.algorithm)
val input = new FileInputStream("file")
iterateStream(input){ (data, length) => 
    md.update(data, 0, length)
}
md.digest

The iterateStreamfunction on line 3, which you could add to a library is:

iterateStream第3行功能,你可以添加到库:

def iterateStream(input: InputStream)(f: (Array[Byte], Int) => Unit){
    val buffer = new Array[Byte](512)
    var curr = input.read(buffer)
    while(curr != -1){
        f(buffer, curr)
        curr = input.read(buffer)
    }
}

The ugly duplicated code (where the input is read) ends up in the library, well tested and hidden away from the programmer. I feel that the first block of code is less complex than the Iterator.continuallysolution.

丑陋的重复代码(读取输入的地方)最终在库中,经过良好测试并远离程序员。我觉得第一块代码没有Iterator.continually解决方案那么复杂。