[plt-scheme] v4 questions

From: Ryan Culpepper (ryanc at ccs.neu.edu)
Date: Mon Mar 31 03:32:05 EDT 2008

Mark Engelberg wrote:
>>  I looked at that, and what I see is a way to delay evaluation of
>>  expressions in classes -- and that's an easy exercise using structs in
>>  mzscheme.  Imitating the first example in the chapter:
> 
> As far as I know, the lazy keyword can be used for any immutable
> variable, and is not just limited to expressions in classes, but I
> can't readily find examples to prove that.
> 
> As I recall from my brief time working with Scala, Scala's evaluation
> mechanism makes no distinction between variables and functions with no
> arguments, so if a variable is bound to such a thunk, it automatically
> evaluates when the variable is dereferenced.  (In other words, typing
> thunk and thunk() is equivalent, although there's some extra syntax
> you can use to get at the actual thunk rather than auto-evaluating it
> if you absolutely need to).  They do this so that if you want to
> change a class variable into an accessor method, you don't need to go
> making changes elsewhere in your program in the way the member
> variable is accessed.
> 
> My guess is that the lazy keyword essentially binds the variable to a
> delay-like thunk, but no force is necessary because of the way all
> thunks are auto-evaluated.

I would expect that auto-forcing is implemented as (local) syntactic 
sugar (perhaps informed by types) rather than a (global) burden on the 
evaluator.

If that's the case, you can get the same effect in Scheme using macros:

   #lang scheme/base
   (require scheme/promise)

   ;; (define-lazy var:identifier rhs:expression)
   (define-syntax-rule (define-lazy var rhs)
     (begin (define tmp (delay rhs))
            (define-syntax var
              (syntax-id-rules (set!)
                [(set! var expr)
                 (set! tmp (delay expr))]
                [(var . args)
                 ((#%expression var) . args)]
                [var
                 (force tmp)]))))

   ;; Example
   (define-lazy x
     (begin (display "evaluating x\n")
            5))

   (+ x x)

   (define (change-it)
     (set! x (begin (display "the new x\n") 10))
     (display "about to compute x^2\n")
     (* x x))

The 'define-lazy' macro creates a separate variable to hold the promise 
and defines the given name as a macro that masquerades as a variable (it 
can even be assigned to!) but implements the lazy semantics.

With a little more verbosity, you could write a different version that 
disallowed mutation, or allowed access to the underlying promise.

Ryan

> _________________________________________________
>   For list-related administrative tasks:
>   http://list.cs.brown.edu/mailman/listinfo/plt-scheme



Posted on the users mailing list.