[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

simpler srfi 45 implementation



Eli wrote the following version:

(module lazy1 mzscheme-no-promises

  (provide lazy delay force promise?)

  (define-struct promise (p))

  (define-syntax lazy
    (syntax-rules ()
      [(lazy exp) (make-promise (lambda () exp))]))

  (define-syntax delay
    (syntax-rules ()
      [(delay exp) (lazy (make-promise (list exp)))]))

  (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)]))))
When Phil Bewig tried this for his SRFI-41, a substantial slow down (factor 100) was found for:
 
(stream-ref
  (stream-of (list a b c)
    (n in (stream-from 1))
    (a in (stream-range 1 n))
    (b in (stream-range a n))
    (c is (- n a b))
    (= (+ (* a a) (* b b)) (* c c)))
  50)
 
Phil asked me what was wrong. The problem is in the cond-clause marked with <---- in the above code. The promise is not lifted. After replacing the marked cond-clause as follows, things ran as fast as before:
 
            [(promise? p)
             (let* ((v (force p)))
              (if (not (pair? (promise-p prom)))
                  (set-promise-p! prom (list v)))
              (car (promise-p prom)))]
Jos Koot

((((lambda(x)((((((x x)x)x)x)x)x))
   (lambda(x)(lambda(y)(x(x y)))))
  (lambda(x)(write x)x))
 'greeting)