Renaming SPECIFIER => CONTEXT ?

There was a typeset in historical Rebol that was called ANY-OBJECT!, that tried to pull together anything that had WORD! keys that could be used as a binding target:

r3-alpha>> help any-object!
ANY-OBJECT! is a typeset of value: make typeset! [
    object! module! error! task! port!
]

I had sort of a naming philosophy (which I still have) that you shouldn't name the category based on one of its instances like this. Several reasons, but one is that it certainly confuses the implementation when you extract the pointed-to entity out of a cell:

 if (Cell_Type(cell) == TYPE_ERROR) {
     Object* = Cell_Object(cell);  // wait, but it's an ERROR! not an OBJECT!
     ...
 }

You could call it AnyObject, I guess. But that's not the direction I took... instead calling the category ANY-CONTEXT!, and if you saw Context* in the source you wouldn't get confused to thinking it was an extraction from a CONTEXT! cell, because there was no such thing. You knew it was the implementation of a superclass.

Enter "Specifier"

"Specifier"--the aggregated inheritance of binding candidates--has moved from an implementation detail to something which is rising to the surface of user awareness. For that, it's a lousy name... and am near-certain I want to take "Context" for it.

I like Context better than Environment, as it's shorter and leaves environment for "environment variables" (which being a script-class language Ren-C needs to be better at interacting with than it is today).

We could say the other types are ANY-DICTIONARY!, although the name DICTIONARY! has been suggested as a replacement for MAP!, since we are thinking of MAP more as a function now. But Dictionary may make more sense for things that only permit "words" as keys.

A CONTEXT! itself--as a composition of other dictionaries (and possibly even just programmatic code that answers value-for-WORD!)--may itself be categorized as an ANY-DICTIONARY!

Implementation Variance Needs Work

So something that has happened in the messy evolution of the code is that the one-size-fits all Context* data structure that backed things like OBJECT!, ERROR!, MODULE! etc. became fractured around the time of Sea of Words and LET.

Modules do not use the same representation, and have to be enumerated completely differently. There's not really a lot of generic code that acts the same way for OBJECT! and MODULE!, to the point that we'd be better off dispelling the illusion in the C sources and making Module* its own distinct type.

There's a lot to consider here about what the limits of "Amish" implementation are:

  • I'm pretty much sold on the known-integer-values concept for Frame. And if I say that drifting away from that destroys what the project is, then it almost certainly does--because I'm known for being iconoclastic about a fair number of Rebol sacred cows.

  • BUT taking a diverging approach for Module from "parallel arrays of Key and Value cell indexed by integer" has proven essential. Floating variable stubs hanging off the word symbols themselves is an answer that has been critical in giving some legitimacy to modules, and it still passes the "simple" test for me.

    • R3-Alpha was utterly hopeless, and Red will be too if they follow down that path (should they ever get modules). I do not think this is a problem appropriate to approach with two-parallel-arrays.
  • Objects are kind of a wild card. Given their attempt to be dirt-simple, we might more accurately call the current version "Struct" or "Structure" instead (major annoyance in C naming the variables though, Struct _struct, to dodge the struct keyword?)

    • People want to dynamically add and remove keys from objects. Rebol2 and Red don't allow it, and R3-Alpha only permitted growth (so the index numbers stored in words that were bound at an index wouldn't be invalidated)

    • Moving to a more amortized implementation that spreads and shares keys gets you to something more like a database, where you can't point to little contiguous packets of memory and say "there is the object."

    • As I said above, I think this was a necessity for Modules. But the simple implementation that works quite well for them wouldn't scale to tens of thousands of objects which have keys with the same name.

    • There's plenty of prior art and writeups of how JavaScript engines and others have approached this, and gotten it to be fast.

Anyway, this all kind of culminates in saying that objects are due for a reckoning at some point. We want to err on the side of simplicity over optimized complexity, but there may be a sufficiently elegant way to attack objects that can grow and shrink effectively and having better code overall than we have today.

Anyway, Back To The Naming Issue...

The above sort of reveals why ANY-OBJECT! isn't a good name for ANY-DICTIONARY or ANY-BINDTARGET?.

Hm, maybe we consider ANY-BINDABLE? to be the category for things that can be bound to, and come up with another name for anything that can be bound? ANY-REFERENCE?

Eh, that sounds confusing. Dictionary may be about as good as it gets (?)

So basically, Dictionary would be a superclass offering lookup from Word Symbol => Value. If you wanted anything else from it, you would have to figure out what subclass it was, because how you do things like enumerate keys and values diverges significantly.

Or Maybe Some Unifying Theory Will Come Along?

It could be, that everything--including OBJECT! and MODULE!, have the "inheritance" powers of what Specifier has today.

Which would mean that you wouldn't have Specifiers. You'd just ask for the binding of a block and maybe get a MODULE! that inherits from an OBJECT!, or an OBJECT! that inherits from a MODULE!, or a LET! that inherits from a LET! that inherits from an OBJECT!, etc.

It all warrants more thought, and maybe a quick attempt to swap out the current OBJECT! implementation with something like V8's Hidden Classes and see how it meshes with the system. I've been so focused on the "bricks" in the language that these sorts of "boring" implementation details have just sort of been left alone while that's sorted out, but now it's getting to the point where there seem to be some answers to guide the shape.

1 Like

This looks good, although I’m not sure I fully understand all the implementation details about OBJECT! and MODULE! which you mention. ‘Context’ feels like a good name to me.

This feels like it’s getting closer to what R does — where ‘environments’ (its name for contexts) are first-class values, which inherit from each other. It doesn’t give ‘inheritance powers’ to other types, but that’s mostly because it has very few datatypes in the first place.

BINDABLE is wrong, but thinking about this in the source and being fully literal about it, the superclass could be called "Binding":

 Binding* binding = Cell_Binding(cell);

And that would give you back something you knew to be a type that can serve as a binding.

ANY-BINDING?.. perhaps.