[Haskell-cafe] Strange memory consumption problems in something that should be tail-recursive

Jefferson Heard jeff at renci.org
Tue Feb 13 16:49:22 EST 2007


Ha!  You're right!  I didn't think about the laziness aspect of it.  Anyway, 
the non tail-recursive version fixed the problem.  Thanks!

On Tuesday 13 February 2007 16:32, Bernie Pope wrote:
> Creighton Hogg wrote:
> > On 2/13/07, *Duncan Coutts* <duncan.coutts at worc.ox.ac.uk
> > <mailto:duncan.coutts at worc.ox.ac.uk>> wrote:
> >
> >     On Tue, 2007-02-13 at 15:27 -0500, Jefferson Heard wrote:
> >     > Hi, I am running the following code against a 210 MB file in an
> >
> >     attempt to
> >
> >     > determine whether I should use alex or whether, since my needs
> >
> >     are very
> >
> >     > performance oriented, I should write a lexer of my own.  I
> >
> >     thought that
> >
> >     > everything I'd written here was tail-recursive
> >
> >     Isn't that exactly the problem - that it's tail recursive? You do not
> >     want it to be tail recursive since then it must consume the whole
> >     input
> >     before producing any output. You want it to be as lazy as possible so
> >     that it can start producing tokens as soon as possible without
> >     having to
> >     consume everything.
> >
> >
> > This may be silly of me, but I feel like this is an important point:
> > so you're saying that tail recursion, without strictness, doesn't run
> > in constant space?
>
> It is an important point, and a classic space bug (see foldl in the
> Prelude).
>
> It it not the fault of tail recursion per se, in fact tail recursion is
> often important in Haskell too.
>
> > So for example in the case of,
> > facTail 1 n' = n'
> > facTail n n' = facTail (n-1) (n*n')
>
> The problem with this example is that it will build up an expression of
> the form:
>
>    (n1 * n2 * n3 .....)
>
> in the second argument. It's size will be proportional to the number of
> recursive calls made (n).
>
> > You'll just be building a bunch of unevaluated thunks until you hit
> > the termination condition?
>
> To fix it you will want the function to evaluate its second argument
> eagerly:
>
> facTail n n' = facTail (n-1) $! (n*n')
> Cheers,
> Bernie.
>
>
> _______________________________________________
> Haskell-Cafe mailing list
> Haskell-Cafe at haskell.org
> http://www.haskell.org/mailman/listinfo/haskell-cafe


More information about the Haskell-Cafe mailing list