On Fri, 15 Jun 2012, Alexander Blinne wrote: > How do Haskell or Scheme determine when elements are not longer needed?
Just like Python, they use garbage collection - in one sentence, if it can be proved the object (not a OO-object, just a piece of data) will no longer be needed, it can be safely deleted - and the code will work as if nothing happened, because the proof said it won't need this data in the future (so you need a right proving technique). Now, the difference is, Scheme (and Lisps AFAIK) and Haskell (and those functional langs I heard of) posess one neat data type, linked list. They also allow for tail-call recursion, which - if one organises one's code properly - means infinite recursion, if one needs it. Some problems are expressed in an elegant and natural manner as linked lists (head to be processed now and rest/tail to be processed later). Such linked lists are ideal fit for tail-call recursion - you process a head and recurse with results and tail in place of original list (thus becoming a next level head+tail list). If no other piece of code stores your current head in a variable (simply speaking), it can be proven that head is no longer needed. Once you call your function recursively, head is waiting to be GC-ed. Your code does not need to worry about this. Last time I checked, Python didn't have linked lists - arrayed lists are nice, but their elements can't be automatically GC-ed (or, this requires very nontrivial GC algorithm), the easiest way I can think would be replacing them with None manually. I'm not sure if del is performance-nice. Also, around the same time, Python couldn't do tail-call, so the whole point of having linked lists was kind of theoretical. Even more cool, with lazy evaluation (like in Haskell) one can generate lists on a fly and process them like they were statically allocated. Say, you only have a 2GB of ram but would like to process 128GB of list, generated ad hoc as your program runs? Like, counting all even numbers less than 2**39 - this is trivial, I know (2**38), but you could run such code with 2GB of ram. Your code processes head and when it recurses with tail, the new head (next number) is generated, so it can be processed. And so on. And thanks to lazy evaluation, you don't need to think about it, this is the job of compiler to organize your program in such way. Yes, you could also run it in a loop or simulate lazy-eval manually (with yield) but the point here is you can have more choice for your algorithm with some languages and in some other languages (Ruby belongs here, too, AFAIK) you don't use recursion (too much) even if you'd like to. Myself, I love more choice, but of course everybody can have his own preferences. Regards, Tomasz Rola -- ** A C programmer asked whether computer had Buddha's nature. ** ** As the answer, master did "rm -rif" on the programmer's home ** ** directory. And then the C programmer became enlightened... ** ** ** ** Tomasz Rola mailto:tomasz_r...@bigfoot.com ** -- http://mail.python.org/mailman/listinfo/python-list