3

У меня есть некоторый изменчивый scala-код, который я пытаюсь переписать в более функциональном стиле. Это довольно сложный фрагмент кода, поэтому я пытаюсь реорганизовать его на куски. Моя первая мысль была такая:Лучший функциональный подход

def iterate(count:Int,d:MyComplexType) = { 
    //Generate next value n 
    //Process n causing some side effects 
    return iterate(count - 1, n) 
} 

iterate(2000000,initialValue) 

Это, похоже, не функциональны все для меня, так как я все еще имеют побочные эффекты, смешанные на протяжении всего моего кода. Моя вторая мысль была таково:

def generateStream(d:MyComplexType):Stream[MyComplexType] = { 
    //Generate next value n 
    return Stream.cons(n, generateStream(n)) 
} 

for (n <- generateStream(initialValue).take(2000000)) { 
    //process n causing some side effects 
} 

Это казалось лучшим решением для меня, потому что, по крайней мере я изолирован моего функционального кода значения поколения от изменяемого кода стоимости обработки. Тем не менее, это намного меньше, чем память, потому что я создаю большой список, который мне действительно не нужно хранить.

Это оставляет меня 3 варианта:

  1. Написать хвостовую рекурсию функцию, стиснуть зубы и реорганизовать код значения Обрабатывающий
  2. Используйте ленивый список. Это не приложение, чувствительное к памяти (хотя оно чувствительно к производительности)
  3. Придумайте новый подход.

Я думаю, что я действительно хочу, это лениво оцененная последовательность, где я могу отбросить значения после того, как я их обработал. Какие-либо предложения?

+0

Является ли d of n функцией d из n-1 или более сложной связью? – sblundy

+0

Да, n может быть вычислено исключительно из d, но результат не является детерминированным, и тот же d не всегда будет давать одно и то же n. – dbyrne

ответ

6

Помните, что критически важные алгоритмы часто работают лучше при изменении. Поэтому остерегайтесь преждевременной де-оптимизации!

В Scala 2.8 вы можете использовать Iterator.iterate для создания бесконечной последовательности без сохраненных значений. Но я не уверен, что один будет ключевым шагом для реорганизации кода, чтобы быть более функциональным. Это то, что часть процесса с побочными эффектами является сложной задачей.

Вы можете поместить все это в итерации блока:

Iterator.iterate(initialState)(x => { 
    // create a new state based upon state x 
}).drop(2000000).next 

, где теперь вы определили бесконечный поток обработки путем последовательного изменения вашего исходного состояния. Вы выбрасываете первые 2000000 значений (один из которых является начальным значением), а затем получите следующий (который является 2000000-м сгенерированным значением). Попробуйте это с помощью 0 и x => x + 1, чтобы увидеть его в действии.

+0

Спасибо! Это ТОЧНО, что я искал! – dbyrne

3

Я думаю, что вы хотите использовать Range, если все, что вы делаете, создает Seq из int от 0 до 2000000. Это приятно и лениво, по крайней мере, в 2.7.

+0

Извините, я думаю, что мой первоначальный вопрос был неясным, потому что я упростил его. Мне не нужен диапазон от 0 до 2000000. Seq состоит из сложной структуры данных. Исходный код был изменен, чтобы отразить это. – dbyrne

Смежные вопросы