Lazy Evaluation and Promises in Racket | Schema Programming Part 16
Racket is an eager (strict) language by default: arguments are evaluated before the function is called. But sometimes, you want to wait.
Advertisement
Delay and Force
Racket provides delay to suspend a computation and force to run it.
(define p (delay (begin (display "Running...") (+ 1 1))))
; Nothing happens yet...
(force p)
; Output: Running...
; Returns: 2
(force p)
; Output: (none) - Result is cached!
; Returns: 2
The result is memoized (cached). This is called a Promise.
Infinite Streams
We can use lazy evaluation to define infinite lists.
(define (integers-from n)
(stream-cons n (integers-from (+ n 1))))
(define nats (integers-from 0))
(stream-ref nats 5) ; 5
(stream-ref nats 1000) ; 1000
Because the recursion is wrapped in a stream-cons (which implicitly delays the rest), the infinite loop doesn't run forever; it only generates numbers as we ask for them.
#lang lazy
If you want everything to be lazy (like Haskell), Racket has a language for that!
#lang lazy
(define x (/ 1 0)) ; No error yet!
(define y 10)
y ; Returns 10, x never explodes
Advertisement
Summary
Lazy evaluation allows for elegant handling of infinite data and complex flow control efficiency. Whether using explicit delay/force or the full #lang lazy, Racket supports this paradigm fully.
What happens when you 'force' a promise a second time?
Md Nasim Sheikh
Software Developer at softexForge