David Shaked
David Shaked

Reputation: 3381

Racket: lazy evaluation within some scope

Racket provides a language extension for lazy evaluation that simply requires a #lang lazy header in the beginning of some file to change the evaluation strategy throughout the file.

However, this standard approach allows only a course level of granularity; A finer approach is needed to confine lazy evaluation to some defined scope.

Does Racket provide some standard approach to confining a lazy evaluation strategy to some scope? I'm looking for something like the following:

(eval-lazy (+ 2 2)) ;; only available by explicit or implicit call-by-need

Upvotes: 0

Views: 1892

Answers (1)

Sylwester
Sylwester

Reputation: 48745

#lang lazy is a completely different language than #lang racket. Yes, you can mix and match some parts, but it can get messy dealing with lazy values from #lang lazy in a #lang racket module.

Every scheme, thus also racket, has delay and force:

(define promise (delay (+ 2 2)))
(force promise) ; ==> 4

However that is just syntax sugar anyway since you can do it like this:

(define promise (thunk (+ 2 2)))
(promise) ; ==> 4

And of course thunk is just syntax sugar for anonymous function with no arguments:

(define promise (lambda () (+ 2 2)))
(promise) ; ==> 4

Now delay actually is slightly more complex since if you call these functions it will run the expression every time. To prevent that we memoize the result. Here I'll implement your eval-lazy as a macro:

(define ^not-calculated (list #f)) ; unique value
(define-syntax eval-lazy
  (syntax-rules ()
    ((_ expression)
     (let ((value ^not-calculated))
       (lambda ()
         (when (eq? ^not-calculated value)
           (set! value expression))
         value)))))

As with the thunk and lambda just calling the result will force it.

Streams

Racket provides a stream library which can be used to do 90% of all algorithms in a way where you do abstract each step as it's own process where you can compose them together without getting the penalty of lists. Streams are just delayed values in cons popularized in SICP

Upvotes: 3

Related Questions