The Return of ALIAS?

Rebol2 had a strange concept of the ability to create aliases for words:

rebol2>> alias 'append "foo"
== foo

rebol2>> foo [a b c] <d>
== [a b c <d>]

rebol2>> foo: 10
== 10

rebol2>> append
== 10

(You might wonder why it takes a string, vs. being alias 'append 'foo. The problem is that if you tried that, the fact that merely mentioning words creates variables for them in historical Rebol would mean that FOO appeared to already exist as an unset variable. The alias wouldn't override it.)

So I've actually been wondering about a more modern version of ALIAS. Because right now we have a sort of pain point on the idea that you can only create bound references to something when the names match up exactly. If you have the thing under a different name, then you have to create a proxy variable to hold the value with the right name... but then you disconnect seeing updates of the original thing.

This could be particularly useful in module imports, where currently you don't see updates if something you import changes in the module you imported from. EXPORT should likely default to providing declarations as read-only, and you should have to do something special if the importers can write a variable. But it's come up frequently (both the desire to see updates, and to be able to write and have the changes seen by the module and other importers, without going through a level of indirection like an object)

2 Likes

So the easiest way to implement this seems to be as a form of ACCESSOR:

A Dream For Debugging: Generalized Accessors

With that, we could make constructs like:

import [@some-module, exported-name <as> local-name]
;
; or more brief but potentially confusing dialected Rebol-y
;
import [@some-module, local-name: exported-name]  ; not an assignment, but...

The accessor could be rigged up so that accesses via LOCAL-NAME see changes in the variable that the module exported as EXPORTED-NAME. The module could perhaps even be unloaded and reloaded, synchronizing the exports. (Not being able to patch a module and reload it without exiting and restarting the interpreter was a pain point for @BlackATTR while debugging modularized QUERY.)

So it's pretty clear that by default, you shouldn't be able to write to a module's state. Since modules can be shared, I don't know if it's ever a good idea (unless you are sure you're the only client of the module?) So writing to the accessors created for imports would be a rare thing.

And it seems like you might want assignment to mean something else--e.g. "I want to take back this variable for other uses, I don't need the module export anymore." So maybe there's an accessor pattern here where writing to the variable "de-accessors" it?

We might consider the nuance of:

 g: getter $var
 s: setter $var
 a: alias $var

Maybe a GETTER can only read, but errors on writes... a SETTER can read and write... and an ALIAS will read, but if you ever write it the accessor is disconnected from VAR and it just holds a new value?

I just realized that even though these are enfix, we can now pass them refinements!

So it could be (a: alias:weak $var) and then setters could be set-only, while an ordinary alias permits both reads and writes where the write will write-through to the original variable... but weak makes writes unlink it from the variable.