[racket] Declarative Prototype Object Extension - looking for feedback

From: Ryan Culpepper (ryanc at ccs.neu.edu)
Date: Wed Jan 23 11:41:45 EST 2013

On 01/23/2013 08:57 AM, Lewis wrote:
> I'd always found prototype object systems interesting, and thought
> they might be a good fit for racket - so I made one about a month or
> so ago
>
> Features:
> - Prototype based, no distinction between classes and instances.
> - Multiple inheritance, methods are looked up in depth first search
> - Declarative syntax, can create an object with a single macro, no need to clone
> and mutate
> - Immutable objects, which can be inherited by and inherit from mutable ones
>
> https://gist.github.com/4605785  - go to line 195 shows its usage.
>
> Basically, I am after feedback on my code, the concept in general, and
> anything really. I actually use it over the  java-style class object
> system racket has, it's very much my vision of what objects should be
> like. But yes, any feedback would be welcome.

It looks good. Here are a couple comments:

You use 'syntax-local-introduce' and 'syntax-local-get-shadower' to bind 
'self', whereas it would be simpler to use syntax-parameters. Look at 
"Keeping it Clean with Syntax Parameters". (You are already avoiding 
many of the problems of other unhygienic approaches by using 
'syntax-local-get-shadower'... but syntax parameters put a nicer 
interface on it.)

Your struct definition for 'immutable-object' isn't used anywhere, so 
perhaps it's leftover from previous experiments code, but its 
declaration of a 'parents' field doesn't change the inherited field 
'parents' from being mutable to immutable; it just adds another one. 
AFAIK, there's no simple way to have immutable and mutable variants of a 
struct type where immutability is enforced by Racket without some kind 
of indirection. By indirection I mean something like the hash: you use 
mutable hashes for mutable objects and immutable hashes for immutable 
objects. But it's harder for the parents fields. In the past when I've 
hit this problem I've just defined two variants and handled them 
separately (possibly with a super-struct with some shared fields), but 
I'm not thrilled with that solution either.

Finally, it looks like your lookup operation (the prop:procedure handler 
and the 'lookup' helper) don't distinguish between "I found the key 
(msg), and its value is null" and "I didn't find the key". And the 
recomputation of (p msg) in 'lookup' looks like it could make getting a 
property take time exponential in the length of the parent chain to the 
property.

Ryan


Posted on the users mailing list.