Каким образом можно закодировать цикл чтения-while в Scala?

Что такое "правильная" запись стандартного цикла чтения-while в Scala? Собственно я имею в виду, написанный с помощью 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 правильный и работает, но он чувствует себя очень не-w64 > -ish. Для одного это буквальный перевод кода Java, не использующий ни одно из преимуществ Scala. Кроме того, он на самом деле длиннее кода Java! Мне действительно кажется, что я что-то упускаю, но я не могу понять, что.

Я новичок в Scala, поэтому я задаю вопрос, чтобы не попасть в ловушку написания кода стиля Java в Scala. Меня больше интересует способ Scala решить эту проблему, чем в любом конкретном вспомогательном методе, который может быть предоставлен API Scala для хэш файла.

(Я заранее извиняюсь за свои ad hoc Scala прилагательные в этом вопросе.)

Ответ 1

На основании сообщения Rex, о котором он упомянул:

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

Вы должны заменить переменную var readLen +, а {...} с ней, она дает тот же результат.

Как упоминал Рекс, он работает с scala 2.8.

Ответ 2

Что предлагает Рекс Керр в своем комментарии следующее:

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. Он получает выражение, которое оценивается непрерывно, создавая бесконечное Stream оцененного выражения. takeWhile - это перевод из условия while. foreach является телом while -loop.

Ответ 3

Как насчет функции карри? Вы получаете 11 строк кода Scala:

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

Функция 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)
    }
}

Уродливый дублированный код (где ввод считывается) заканчивается в библиотеке, хорошо протестирован и скрыт от программиста. Я чувствую, что первый блок кода менее сложный, чем решение Iterator.continually.