(defsuite "promises" (deftest "delay creates a promise" (do (assert (promise? (delay 42))))) (deftest "delay does not evaluate immediately" (do (let ((count 0)) (let ((p (delay (do (set! count (+ count 1)) count)))) (assert= 0 count))))) (deftest "force evaluates the expression" (do (assert= 42 (force (delay 42))))) (deftest "force with arithmetic" (do (assert= 10 (force (delay (+ 3 7)))))) (deftest "force memoises result" (do (let ((count 0)) (let ((p (delay (do (set! count (+ count 1)) count)))) (force p) (force p) (assert= 1 count))))) (deftest "force returns same value on repeated calls" (do (let ((p (delay (+ 1 2)))) (assert= 3 (force p)) (assert= 3 (force p))))) (deftest "make-promise creates an already-forced promise" (do (let ((p (make-promise 99))) (assert (promise? p)) (assert= 99 (force p))))) (deftest "make-promise memoises without evaluating" (do (let ((count 0)) (let ((p (make-promise 42))) (force p) (force p) (assert= 0 count))))) (deftest "promise? returns true for delay" (do (assert (promise? (delay 1))))) (deftest "promise? returns true for make-promise" (do (assert (promise? (make-promise 1))))) (deftest "promise? returns false for non-promise" (do (assert= false (promise? 42)) (assert= false (promise? "hello")) (assert= false (promise? nil)) (assert= false (promise? (list 1 2))))) (deftest "force non-promise returns value unchanged" (do (assert= 42 (force 42)) (assert= "hi" (force "hi")) (assert= nil (force nil)))) (deftest "delay captures environment" (do (let ((x 10)) (let ((p (delay (+ x 5)))) (assert= 15 (force p)))))) (deftest "delay-force basic" (do (assert= 42 (force (delay-force (delay 42)))))) (deftest "delay-force chains" (do (assert= 5 (force (delay-force (delay-force (delay 5))))))) (deftest "delay with string" (do (assert= "hello" (force (delay "hello"))))) (deftest "delay with list" (do (assert-equal (list 1 2 3) (force (delay (list 1 2 3)))))) (deftest "delay with function call" (do (assert= 6 (force (delay (* 2 3)))))) (deftest "nested delay" (do (let ((p (delay (delay 99)))) (assert (promise? (force p)))))) (deftest "force already forced promise" (do (let ((p (make-promise 7))) (assert= 7 (force p)) (assert= 7 (force p))))) (deftest "lazy stream first element" (do (define (stream-cons x s) (delay (list x s))) (define (stream-car s) (first (force s))) (define (stream-cdr s) (nth (force s) 1)) (let ((s (stream-cons 1 (stream-cons 2 (stream-cons 3 nil))))) (assert= 1 (stream-car s)) (assert= 2 (stream-car (stream-cdr s)))))) (deftest "delay-force is a promise" (do (assert (promise? (delay-force (delay 1)))))) (deftest "force with side effects runs once" (do (let ((log (list))) (let ((p (delay (do (set! log (cons 42 log)) 42)))) (force p) (force p) (assert= 1 (len log)))))) (deftest "make-promise with nil" (do (let ((p (make-promise nil))) (assert (promise? p)) (assert= nil (force p))))) (deftest "delay in let binding" (do (let ((p (delay (+ 10 20)))) (assert= 30 (force p))))))