Re: simpler srfi 45 implementation
Eli Barzilay 13 Nov 2007 12:44 UTC
On Nov 13, Jos Koot wrote:
> Eli wrote the following version:
>
> [...]
> (define (force promise)
> (let ([p (promise-p promise)])
> (cond [(procedure? p)
> (let ([promise* (p)])
> (unless (pair? (promise-p promise))
> (if (promise? promise*)
> (begin (set-promise-p! promise (promise-p promise*))
> (set-promise-p! promise* promise))
> (set-promise-p! promise (list promise*))))
> (force promise))]
> [(pair? p) (car p)]
> [(promise? p) (force p)] <----
> [else (error "Invalid promise, contains" p)]))))
> [...]
Actually, I use a variation of that, which you can see at
http://svn.plt-scheme.org/plt/trunk/collects/lazy/promise.ss
(The file has four versions of `force' : the first is like the above,
the second deals with multiple values, the third deals with multiple
values only for the delay/force case, and the last adds exception
catching.)
The differences between this and the version that you quoted are
mostly technicalities, and the code that I have can still use this
optimization. I couldn't verify that the version I'm using enjoys the
same speedup -- Phil: do you have the code needed to run Jos's example?
... and there's a "BUT":
I was aware of the possible optimization at the time, but didn't find
any example where it mattered. However, if you do put it in:
> [(promise? p)
> (let* ((v (force p)))
> (if (not (pair? (promise-p prom)))
> (set-promise-p! prom (list v)))
> (car (promise-p prom)))]
then you do the recursive forcing of `p' in a non-tail conext. My
(vague, not formal at all) feeling about these "referral promises" is
that they do happen in places where the original code had a tail call,
so it might be a bad idea to break it.
So I don't know whether it should be included or not -- do you see
that it's not doing any damage?
--
((lambda (x) (x x)) (lambda (x) (x x))) Eli Barzilay:
http://www.barzilay.org/ Maze is Life!