[plt-scheme] ivar equivalent (circa class100.ss) available with current class system?

From: Matthew Flatt (mflatt at cs.utah.edu)
Date: Fri Aug 5 17:11:05 EDT 2005

At Fri, 5 Aug 2005 13:49:05 -0700 (PDT), Danny Yoo wrote:
> I've been reading through some of the class material from readscheme.org,
> and was curious why the IVAR function from the old class system doesn't
> exist in the current class system:

In the old class system, an object was just a collection of fields (or
"instance variables"), and a method was a function-valued field.

This approach makes sense when the base language has closures. But it's
also expensive when a class with many methods is instantiated many
times; every instance has its own closure for each method.

> This seemed a bit unusual to me; it's a great error message, but I don't
> see in the reference documentation why this restriction is enforced.  Is
> it a deliberate design decision for with-method to prevent methods from
> leaking out of their instances?

Yes. The implementation of a method is a procedure that accepts `this'
as the first argument (so it doesn't have to be closed over each
instance). If you could extract the method procedure directly, you
could apply it to some other object, and method/field accesses within
the method would go wrong.

The object system could provide something like `ivar' that creates an
object-specific closure on demand. It would be similar to your macro:

>   (define-syntax ivar
>     (syntax-rules ()
>       [(ivar instance-expr method-name)
>        (let* ((instance instance-expr)
>               (method-name
>                (lambda args
>                  (send/apply instance method-name args))))
>          ;; used the let to get inferred-name of the lambda
>          ;; initialized properly
>          method-name)]))

Two things to note:

 * There's an explicit closure allocation.

 * To make it work with an arbitrary method, you had to use `args' and
   `apply', which will not perform well.

A built-in `ivar' could do better on the second issue, since it can
know more about the target method.

For most cases, we've been content to write

  (lambda (x y z) (send o m x y z))

instead of

  (ivar o m)

Using `lambda' avoids the second issue above, and it makes the closure
allocation explicit.


Posted on the users mailing list.