Как мне избежать непреднамеренного захвата локальной области видимости в функциональных литералах?

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

Вот короткий пример ( ОБНОВЛЕНО , см. Ниже):

def method: Iterator[Int] {
    // construct some large intermediate value
    val huge = (1 to 1000000).toList        
    val small = List.fill(5)(scala.util.Random.nextInt)
    // accidentally use huge in a literal
    small.iterator filterNot ( huge contains _ )    
}

Теперь iterator.filterNot работает лениво, и это здорово! В результате мы ожидаем, что возвращенный итератор не будет потреблять много памяти (действительно, O (1)). К сожалению, мы совершили ужасную ошибку: поскольку filterNot ленив, он сохраняет ссылку на литерал функции huge contains _ .

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

(Я только что допустил такую ​​ошибку, которую долго выслеживал! Такие вещи можно поймать по дамам кучи ... )

Как лучше всего избежать этой проблемы?

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

ОБНОВЛЕНИЕ: приведенный ранее пример был глупым, как показывает ответ huynhjl ниже. Это было:

def method: Iterator[Int] {
    val huge = (1 to 1000000).toList // construct some large intermediate value
    val n = huge.last                // do some calculation based on it
    (1 to n).iterator map (_ + 1)    // return some small value 
}

На самом деле, теперь, когда я немного лучше понимаю, как эти вещи работают, я не так беспокоюсь!

7
задан Scott Morrison 18 October 2010 в 16:22
поделиться