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
____________________
Racket Users list:
http://lists.racket-lang.org/users