unofficial mirror of guile-user@gnu.org 
 help / color / mirror / Atom feed
* another Q on tail calls
@ 2015-02-18 17:20 Matt Wette
  2015-02-18 17:38 ` Taylan Ulrich Bayırlı/Kammer
  0 siblings, 1 reply; 2+ messages in thread
From: Matt Wette @ 2015-02-18 17:20 UTC (permalink / raw)
  To: guile-user

[-- Attachment #1: Type: text/plain, Size: 683 bytes --]

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


[-- Attachment #2: Type: text/html, Size: 1266 bytes --]

^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: another Q on tail calls
  2015-02-18 17:20 another Q on tail calls Matt Wette
@ 2015-02-18 17:38 ` Taylan Ulrich Bayırlı/Kammer
  0 siblings, 0 replies; 2+ messages in thread
From: Taylan Ulrich Bayırlı/Kammer @ 2015-02-18 17:38 UTC (permalink / raw)
  To: Matt Wette; +Cc: guile-user

Matt Wette <mwette@alumni.caltech.edu> 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



^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2015-02-18 17:38 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2015-02-18 17:20 another Q on tail calls Matt Wette
2015-02-18 17:38 ` Taylan Ulrich Bayırlı/Kammer

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).