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.
Sorry, I have two very different examples of how stuff could "leak". There really was no relation between the float problem and the string parsing so I shouldn't have mixed them like that.
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 ratherfail-blocks with string arguments vs fail-blocks with object arguments.
Once again, the problem was with my description. I wanted to say what you just said but "exceptions" slipped in when trying to make an analogy of how the set of objects to be used as parameters might be organized. Many OO languages have a hierarchy of error and warning objects and I was thinking of something like that. I didn't mean to bring any other aspect of exceptions into the discussion (right now I am implementing a Squeak VM and am finding them very troublesome...)
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.
You were clear, but I added the comment about non local returns just in case someone else following the discussion isn't aware of the importance of that aspect. In particular, this is something that is used very rarely in Smalltalk-80 compared to in Self.
["system slots" in tinySelf 0]
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.
I tried several different designs going to both extremes (lots of implicit information vs explicit) and it isn't easy to find a good balance. Perhaps there isn't one, and each situation a different choice is the best.
Just as an example, in one version of tinySelf 0 (done before Self 3 came out, so this didn't have annotations) each slot had three words in the map: the name, a value and a code pointer. The system just called the indicated code with the supplied value (along with the receiver). The code for a constant slot (shared by all constant slots in the system) just returned the value, while the code for a data slot indexed the receiver. The code for a method that hasn't been compiled yet was the interpreter itself (the value is the bytecodes) while if it has been compiled it was the native code (the value is still the bytecodes, but that is ignored).
This Forth-like version has almost everything implicit. You can create many new types of slots, but there is no good wait of doing stuff with them other than their default behavior. The other extreme was to have each slot be a full object, which is hardly efficient in terms of memory but does make everything very explicit.