On Dec 28, 2010, at 11:59 AM, Jecel Assumpcao Jr. wrote:

 

David Ungar wrote on Mon, 27 Dec 2010 18:50:51 -0800
> On Dec 27, 2010, at 11:03 AM, Jecel Assumpcao Jr. wrote:
> > [gripe - strings instead of objects for annotations]
>
> The string part was an easy implementation way to save space. Sure
> storing objects would have been nicer.In fact they were changed back
> and forth to objects in a way that was transparent. Annotations were
> meant to be functional, so you could replace them but not change them
> in place.That saves a lot of space. Remember that every slot in every
> point object conceptually had its own annotation.

Yeah, I didn't find a good alternative that would be reasonably space
efficient. In the syntax, an annotation can span a number of slots. But
in my designs I ended up just replicating the annotation for each slot
separately (sharing when possible). Hmmmm.... just now I see that there
is no reason to insist that maps be "flat". Just because the old object
tree was replaced by annotation doesn't mean that the maps couldn't
remain a tree. Then an annotation that only appears once in the source
would only need to appear once in the runtime structure. Lookup
performance is not as important in a compiler.


yes



> > [gripe - strings in the parameters of fail blocks]
> Not sure what you mean here about Ole's extractor.

It was easy for unrelated parts of the system to leak into the snapshot
that was being extracted. One example is floating point for the
factorial - there is one branch in the "power" function where the result
could be a float (but it never is in this application) and so you get
this huge overhead. The other place is string functionality: the
factorial app just needs enough to print its results but due to code
like


If the result could be a float, then there isn't much hope for an automatic extractor to know it couldn't be, unless I don't understand your example.



+ a = ( |
| asSmallInteger _IntAdd: a IfFail: [| :error. :name. |
('badTypeError' == error) ifTrue: [
" use double dispatching "
a addSmallInteger: asSmallInteger ] False: [
('overflowError' == error) ifTrue: [
" retry after coercing to bigInts "
asBigInteger + a asBigInteger ] False: [
primitiveFailedError: error Name: name ]]]).

you bring in stuff from String. Hmmmm..... this isn't nearly as bad as I
remember since only '==' is being used. I thought there were lots of
'beginsWith:' all over the place.

At one point there may have been beginsWith:, and you could argue (and I would agree) that we would have been better off
making error objects to pass in to fail blocks. The issue there is *not* exceptions vs fail blocks, but rather
fail-blocks with string arguments vs fail-blocks with object arguments.



> IMNSO, exceptions were a botch invented in languages without blocks
> .I never liked the fact that control could invisibly branch off.For instance,
> in a long method with exceptions, containing A; B; C;, you cannot count on
> B being executed if A is executed. At least with fail blocks you can see
> the branch in the return symbol in the block .I know that others like
> exceptions. To me they are like iterators, both were workarounds for
> languages without blocksthat became enshrined in our culture. I prefer
> blocks. But that's just me.

Actually, besides blocks you need non local returns to get the effect of
exceptions and I think Self code is a great example of how to do this.
But when I mentioned "exception objects instead of strings" I was just
thinking of having something like


Yes, of course. To me, "blocks" means blocks + block arguments + block locals + (what squeakers call closure semantics) + non-local return.
Sorry if that wasn't clear.



traits errors = (| isBadType = false. isOverflow = false. .....
|).
badTypeError = (| parent* = traits errors. isBadType = true |).
overflowError = (| parent* = traits errors. isOverflow = true
|).

This wouldn't really help in the '+' method above very much, but with a
more complete hierarchy and some actual functionality in the error
objects rather than them being simple tokens it could make a nice
difference.


Yup, these would be better to pass in to the fail blocks than strings.


> > [tinySelf 0: special constant slot for object annotation]
> That would allow object annotations to be accessed without reflection,
> a change from what I considered tobe the appropriate base-level
> semantics. It is simpler, though. It violates my preferred model of
> object encapsulation.

I agree, but in tinySelf 0 I had a bunch of "system slots" which you
couldn't access by sending messages to their object but which showed up
when talking to a mirror. The annotation slot was the only one I added -
the rest (like the "hidden parent slots" in the block clones and block
activations) were already part of the execution story for Self and I
just reified them.


So, slot types were always a tempting addition, but the problem was where to stop.
If some slots are hidden sometimes, why not have many kinds of hidden slots hidden at various times?
(This brings me right back to Us as a nice unification.)
And you still, as you said, have the problem of reifying slots; in other words the problem solved with slot annotations.

- David



-- Jecel