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

发布于 2024-09-05 05:18:03 字数 1026 浏览 9 评论 0原文

在 Scala 中编写标准 read-while 循环的“正确”是什么?我所说的“正确”是指以类似 Scala 的方式编写,而不是类似 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();

这是我在 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

Scala 代码是正确的并且可以工作,但感觉非常不 Scala 风格。其一,它是 Java 代码的直译,没有利用 Scala 的任何优点。而且它实际上比 Java 代码还要长!我真的感觉自己失去了一些东西,但又想不起来到底是什么。

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

(对于我在这个问题中使用的临时 Scala 形容词,我提前表示歉意。)

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.

Here is the code I have in 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:

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.

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.

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

始于初秋 2024-09-12 05:18:03

根据 Rex 的帖子,他提到:

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

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

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

Based on Rex's post that he mentioned:

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.

As Rex mentioned, it works with scala 2.8.

奢望 2024-09-12 05:18:03

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

关键是 Stream.continually。它获取一个不断求值的表达式,创建一个求值表达式的无限StreamtakeWhilewhile 条件的转换。 foreachwhile 循环的主体。

What Rex Kerr suggests in his comment is the following:

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 Stream of the evaluated expression. The takeWhile is the translation from the while-condition. The foreach is the body of the while-loop.

春夜浅 2024-09-12 05:18:03

柯里化函数怎么样?您的 11 行 Scala 代码变为:

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

第 3 行的 iterateStream 函数,您可以将其添加到库中:

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

丑陋的重复代码(读取输入的位置)最终出现在库中,经过充分测试并且远离程序员。我觉得第一段代码比 Iterator.continually 解决方案简单。

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

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

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

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.continually solution.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文