[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: another Q on tail calls
From: |
Taylan Ulrich Bayırlı/Kammer |
Subject: |
Re: another Q on tail calls |
Date: |
Wed, 18 Feb 2015 18:38:45 +0100 |
User-agent: |
Gnus/5.13 (Gnus v5.13) Emacs/24.4 (gnu/linux) |
Matt Wette <address@hidden> writes:
> Here is another one Q on tail recursion. Is this a tail call? The
> result of (foo) is 10.
>
> At each iteration the loop captures the local variable "n" in a lambda
> and saves in a list. At the end of the iteration "+" is applied to the
> evaluation of all the lambdas. It looks to me like the capture of the
> binding has to invalidate tail-recursion. Is that true?
>
> (define (foo)
> (let iter ((proc-list '())
> (n 4))
> (if (zero? n)
> (apply + (map (lambda (proc) (proc)) proc-list))
> (iter (cons (lambda () n) proc-list)
> (1- n)))))
>
> Motivation: I have been looking into streams programming (from SICP)
> and thinking about delay/force and future/touch.
>
> Thanks,
> Matt
The 'iter' loop uses tail-calls, so it doesn't grow the stack. The
procedure capturing the variable 'n' (actually it's likely to capture
the value 'n' holds in that moment, because the optimizer should be able
to notice that 'n' is never mutated) resides on the heap (and if 'n'
were mutable/mutated it would also reside in a "box" on the heap), so no
stack usage due to the creation of those procedures.
(Maybe the optimizer might do even crazier things and somehow use stack
space for the procedures after all, but it's guaranteed to uphold the
semantics of using constant stack frames for the iteration.)
If you're keen on reading academic papers, I can recommend AI Memo #199,
titled FUNARG, and AI Memo #349 which is the original specification of
Scheme ("R0RS" if you will).
Taylan