Modules vs. Rebol's Contention for Short Words


There's an aversion in Rebol scripts of putting things into sub-contexts. You see it when the math operation tan competes with the color tan.

Despite issues like this being known about since the earliest days, it's certainly telling that there wasn't some immediate backlash, where math: make object! [tan: ...] and color: make object! [tan: ...] were made. Though Red decided to made tanned the color and take tan for the math operation, they didn't follow up by making reddish. They still define red as 255.0.0, and red is not a synonym for the system object as rebol was. (Which is a bad idea, anyway.)

A Fractal of Contention

If you tried to put the operations and colors under "math/xxx" and "color/xxx" as above, you have another problem. MATH is currently purposed as a dialect using "normal" mathematical precedence for expressions. COLOR sounds like it would almost certainly be a local variable name, and you can't say color: color/tan.

When other languages run up against this, they might attack it with case sensitivity. If Rebol were to do that it would be color: Color/tan...but that's not the game here. You can pluralize things maybe... color: colors/tan, but one might also have a variable like colors: [tan red].

All text-based languages have problems like this. BUT Rebol's desire for an English-like aesthetic puts more of a premium price on short words. And its lexical uniformity makes it harder to suss out the "parts of speech" to know what the heck you are reading:

foo/baz/bar mumble/frotz fribble  ; objects? functions? refinements? (?!)

foo.baz(mumble.frotz, bar: fribble)  ; More conventional syntax is clearer

(Note: I'm now thinking that with being a likely SYM-TUPLE!, that the inertness of tuples may be less useful than considering them to be a field-selector operation... and even to let you add fields to ACTION!s, as you can in JavaScript. So math [1 + 2 * 3] could work, but so could math.tangent 0.0. It wouldn't be a refinement, just a member of an aggregate that also could execute in its own right. It's a thought, anyway.)

What About Getting the Brevity That You Pay For?

Very little of what I write involves colors at all (more now perhaps with the HTML console). I'm also not a huge user of trigonometry or floating point math--at least not in Rebol. The kinds of problems I'm interested in for a script language almost never require math outside of integers. I'm more likely to use RED and BLACK as data structure annotations as in a Red-Black Tree. If I ever needed colors or trigonometry, it would be task-sensitive to say whether tan should win as tangent or the color.

Over the long run, if there's going to be any sort of scalability for Rebol...things like the inclusion of colors in global scope has to be something that someone asked for.

So perhaps modules should have a kind of dialected inclusion? There could be a language for telling the trigonometry module "give me the abbreviations". You could ask for sets of things to be bound as the words with no qualification, or others to be bound through a local alias for the module.

If you have common sets of inclusions, you should be able to abstract that. Even C can do this... you can #include a file that includes others.

In any case, I think the core language needs to pare down implicit definitions. Things are moving that direction with the extensions, but those extensions are still poking things into the LIB context without being asked. I give the color and math operations as good examples of things that must be asked to be put into the main binding of the module...otherwise you get them through a name.

What About a Shortcut to a Module's "Needs" Space?

In C++, there is a way of getting out of your "local scope" and up to the global scope:

Right now, getting access to the modules list requires you to do system/modules/mod-name. But what if each module kept a small object for the extensions that it had included, and put it in something like ~?

>> color: ~/colors/tan
== 222.184.135

>> ~/math/tan 0.0
== 0.0

>> math [1 + 2 * 3]
== 7

Someone who is doing a modest amount of trigonometry might prefer to import it named trig and access it as trig. Or import them with full names, or ask the module to abbreviate the names. I'm just talking about a spectrum of options based on how much you use the thing.

Or maybe MATH itself is what binds to TAN. So you'd say math [tan 0.0], and if you use TAN outside of MATH you don't get it.

Or it may be that ~ is just the module itself, where the binding the module did at load time wasn't to necessarily bind everything that was included. e.g. there may be a module field for math which is the math module, but it would bind plain uses of math to lib/math despite the existence of that field.

Further: the idea of importing things locally could be at a function or USE granularity. If only one of your functions mentions trigonometry, why not have that one be function [... <in> ~/trigonometry] [...] If you have multiple functions that want to do this, why not make your own variant, e.g. TFUNCTION, that adds the trigonometry dependency?

Any Methodology Should Be Able To Do Redbol Emulation

These ideas sound like they may bring a lot of concerns and decisions to the average user.

But if you can abstract it to something like Needs: Redbol and have that do all the necessary work to achieve a Rebol2/Red environment, then that would be a good proof of concept.

1 Like

I know WITH isn't a universally popular idea, but if you have objects loaded with these words, you could say:

my-tan: with colors [tan]
my-math-tan: with math [:tan]

I've been using WITH as shorthand for do bind block object for a while and it seems workable, and WITH/ONLY where you need, say:

parse "foo" with/only charsets [some alpha]