[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: Having trouble making a simple recursive inspector.
From clp@parian.bos.marble.com Mon Oct 15 12:00:24 1990
Return-Path: <clp@parian.bos.marble.com>
)
To: self-interest@self.stanford.edu, clp@parian.bos.marble.com
Subject: Having trouble making a simple recursive inspector.
Cc: alex@xait.xerox.com
Status: R
I tried to create a simple recursive inspector just to see if I could.
After a little fiddling I came up with:
_AddSlots: (| irec: = (| :obj m. | m: obj _Mirror. inspect: obj.
m _MirrorSize do:
[|:n| irec: (m _MirrorContentsAt: n) _MirrorReflectee].)|)
Which is called, e.g., via "irec: <an object>" like the normal inspect:
Now I know that even is this did run, it would probably run forever due to
loops in the system structure, but I want to watch it run through the parent
pointer, etc.
It seems to work just fine except that methods won't respond to _MirrorReflectee
for some reason (Grrrr!!). This seems like a needless non-generality! Am I
missing something? Why can't methods allow this? Is there an equally simple
(or any easy) way to do what I want?
Charles
Bay's reply summed it up nicely, but I thought I would add my own $0.02 worth:
First, I am VERY glad you are writing Self programs!
Keep it up!
Now the explanation:
We believe strongly in the benefits of reusing the same code with different representations.
This implies that the code may not distinguish between reading a variable and invoking a function.
How to model this in a programming language?
One way would have been to have different kinds of slots: data slots and code slots.
Had we done this we could have had functions which only evaluated when fetched out of a code slot.
We rejected this approach on two grounds:
1. clutter caused by multiple slot types
2. functions considered harmfull.
In OOP a receiver gets to decide what code to run. But if you have functions
they always do the same thing no matter what the objects are.
I believe that functions perniciously weaken the power of data abstraction by
taking control away from the objects, and by packaging up code without data.
So, we opted for one slot type, and a model that says that an object is always executed
when fetched from a slot. Most objects simply return themselves when they execute.
As a result, you cannot have a naked method in Self, because it would have run when you fetched
it, and you would have gotten the result of the method.
So, we have mirrors. A mirror is a way to handle an object without evaluating it,
much like a "ten foot pole". When doing reflective computation (as your example does)
always stick with mirrors.
David
PS Is this in any of the papers? Should we write something on self-reflection some day?