Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • Home
  • SEARCH
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 3232752
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 17, 20262026-05-17T17:11:52+00:00 2026-05-17T17:11:52+00:00

I’ll ask this with a Scala example, but it may well be that this

  • 0

I’ll ask this with a Scala example, but it may well be that this affects other languages which allow hybrid imperative and functional styles.

Here’s a short example (UPDATED, see below):

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

Now iterator.filterNot works lazily, which is great! As a result, we’d expect that the returned iterator won’t consume much memory (indeed, O(1)). Sadly, however, we’ve made a terrible mistake: since filterNot is lazy, it keeps a reference to the function literal huge contains _.

Thus while we thought that the method would require a large amount of memory while it was running, and that that memory could be freed up immediately after the termination of the method, in fact that memory is stuck until we forget the returned Iterator.

(I just made such a mistake, which took a long time to track down! You can catch such things looking at heap dumps …)

What are best practices for avoiding this problem?

It seems that the only solution is to carefully check for function literals which survive the end of the scope, and which captured intermediate variables. This is a bit awkward if you’re constructing a non-strict collection and planning on returning it. Can anyone think of some nice tricks, Scala-specific or otherwise, that avoid this problem and let me write nice code?

UPDATE: the example I’d given previously was stupid, as huynhjl’s answer below demonstrates. It had been:

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 
}

In fact, now that I understand a bit better how these things work, I’m not so worried!

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-05-17T17:11:52+00:00Added an answer on May 17, 2026 at 5:11 pm

    Are you sure you’re not oversimplifying the test case? Here is what I run:

    object Clos {
      def method: Iterator[Int] = {
        val huge = (1 to 2000000).toList
        val n = huge.last
        (1 to n).iterator map (_ + 1)
      }
    
      def gc() { println("GC!!"); Runtime.getRuntime.gc }
    
      def main(args:Array[String]) {
        val list = List(method, method, method)
        list.foreach(m => println(m.next))
        gc()
        list.foreach(m => println(m.next))
        list.foreach(m => println(m.next))
      }
    }
    

    If I understand you correctly, because main is using the iterators even after the gc() call, the JVM would be holding onto the huge objects.

    This is how I run it:

    JAVA_OPTS="-verbose:gc" scala -cp classes Clos
    

    This is what it prints towards the end:

    [Full GC 57077K->57077K(60916K), 0.3340941 secs]
    [Full GC 60852K->60851K(65088K), 0.3653304 secs]
    2
    2
    2
    GC!!
    [Full GC 62959K->247K(65088K), 0.0610994 secs]
    3
    3
    3
    4
    4
    4
    

    So it looks to me as if the huge objects were reclaimed…

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

No related questions found

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.