Каким образом можно закодировать цикл чтения-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
.