simple object model (was: [self-interest] selfing Self)
Jecel Assumpcao Jr
jecel at merlintec.com
Fri Mar 30 19:59:09 UTC 2001
I am sending a copy of this to the self-interest list. I hope you don't
On Friday 30 March 2001 04:39, Uladzimir Liashkevich wrote:
> Let me join the discussion. This is a very interesting topic to me.
> When I first read about Smalltalk I thought that it is the greatest
> language ever. Then I discovered some difficulties with the language,
> for example absense of multiple inharitance causes strange
> inharitance trees like Object -> ReadStream -> ReadWriteStream.
My favorite example is String, which can't decide if it should be a
Magnitude or a Collection...
> When I read about Self, I felt the same as in the case of Smalltalk.
> Later I discovered the absense of some needful possibilities. One of
> them is constructing objects on the fly. One cannot write something
> like this: (| x:Y: = (| :aX. :aY | ^(| x <- aX. y <- aY |) ) |).
While this doesn't work because slot initializers ("aX" and "aY" in
this case) are always evaluated in the context of the lobby object, you
can get the same results with:
(| x:Y: = (| :aX. :aY. new |
new: (| x. y. parent* = traits clonable |) copy.
new x: aX.
new y: aY.
The reason I used 'copy' above is that I am supposing that you don't
want successive calls to this method to always return the exact same
object, but just the same kind of object. If that is the case but you
don't want the new object to be clonable, we could use the '_Clone'
primitive instead of 'copy' and eliminate 'parent*'.
If you wanted 'x' and 'y' to be constant slots in the new object (you
didn't show that in your example) then things do get much more
complicated. It is still possible to do this using mirrors, however.
But I was indeed trying to make this kind of thing simpler.
> now I'm in process of thinking out a more flexible but yet powerful
> language. By now I have implemented two experimental versions of
> Self. But I need something different.
Me too, but more in the spirit of Self than the Self-inspired languages
of the early 1990s.
> > Like a simple object model: objects are just flat association lists
> > (I'll use Lisp notation below) -
> > (x 3 y 4)
> flat list has an array structure rather than linked list?
By "flat" I meant compared to this form of association list:
((x 3) (y 4))
But it is a *very* interesting question if these should be arrays or
linked lists -
Lists: + can be shared as the continuation (CDR) of several other
+ can be scanned using a single pointer
- since you can point into the "middle" of a list there are
many aliasing problems
- can't be indexed into
+ can be as space efficient as arrays with special encoding
+ easy to split and put together
Arrays: - need three items for scanning: base, index and size
+ no need to waste more than one virtual address per
+ access to any element is equally fast
It is easy to convert one into the other when you need to do some kind
of processing for which the normal format is not very good.
> Do you want to use the same semantics for a objects, arrays and
> hashes? Like, (1 2 3) - array, (x 3 y 4) - object or hash?
> Please describe that semantics a bit more.
Every object is a list, but there are lists which are not formatted
objects (the code examples below, for instance). So I must treat (1 2
3) as an object which does not explicitly list the messages it
understands. In fact, the object "1" has this problem as well, but at
least the number objects have special tags so they don't look like they
might be a regular object. I am still figuring this out.
> > append '(z 9) '(x 3 y 4)
> Is this a message-sending construction? What is the receiver?
No, this was a pseudo Lisp functional notation. This would be more
'(z 9) append: '(x 3 y 4)
though the problem above shows itself here: how does the '(z 9) object
understand the 'append:' message? We would have to force it to be
treated as a plain list, which is getting into the reflective level and
similar to requesting a mirror for an object in Self.
This needs some careful design.
> How to distinguish objects and methods?
I am thinking of making methods internally be objects that have a
special <code> "slot"
... factorial: (n 0
<code> (n < 1 ifTrue:False: 1 '(n * factorial: n-1)
I have other ideas for blocks than quoted lists, but this will do for
now. Hmmm... if instead of "<code>" I used "|" then this would look
more like Smalltalk...
Note that though the argument "n" has a default value of 0, it will be
replaced once this code object is cloned to create a context object.
> Did you get rid off keyworded selectors like a:B:C:?
I used one in the above example, but at the low level the keywords
aren't spread among the arguments. In a higher level graphical editor I
would expect you to be able to write something like
n < 1 ifTrue: 1 False: [n * factorial: n - 1]
My idea is that the arguments would be underlined, but that is hard to
show using ASCII in this email.
> > [these nested lists can act as both "maps" and parents]
> Really good fresh idea.
> It seems that all slots are assignable, doesn't it?
That is something to be fixed. The implemenation must be able to tell
what is changable and what is (normally, at least) constant. In the
NeoLogo implemenation where these ideas came from you could write
make "x 10
and simply change the value of the x "slot". It would be better to do
the same thing by sending a message instead
and you could have the Self rule that unless there is a "x:" method
then "x" is a constant slot. I don't know what the best way to handle
assignments is. I have always felt that assignments and argument
replacement should be somehow related. Kyle doesn't like the fact that
assignment slots must be in the same objects as their data slots in
Self (they can't be moved into the parent objects, for example).
> The first challenge is to invent such system, then it can be
> optimized. Remember that many people doubted that Self can be
> implemented efficiently...
Right, we can always hope that history will repeat itself. On the other
hand, there are many examples of interesting ideas that nobody ever
figured out how to do reasonably well. Dynamic parent slots in Self are
an example (actually, I did figure out a way to do it but haven't tried
More information about the Self-interest