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!