I've written about Rebol's historical idea of walking the source deeply at the beginning, and the mere mention of an ANY-WORD! would lead to a variable being created for it in the user context. This chewed through memory making unnecessary variables, and gave you a situation ripe for typos:
rebol2>> add-ten: func [argument] [
argment: argument + 10
return argument
]
rebol2>> add-ten 20
== 20
rebol2>> argment
== 30
This behavior resembles pre-strict-mode JavaScript, and makes it easy to get bugs
But it's a semantic that some code uses intentionally. And if Rebol2 emulation is to be possible, there has to be some way to do this.
It's also a useful way to work in the console. Browsers still run JavaScript in non-strict-mode by default:
>> function foo() { jkl = 10 }
<- undefined
>> foo()
undefined
>> jkl
<- 10
Simulating Non-Strictness With "Attachment" Binding
In order to overcome the idea of creating variables for every ANY-WORD! to be mentioned, the "Sea of Words" concept was first implemented by making code loaded for a module bind non-specifically to that module. Words held a pointer to the module with no further information about the address of a variable in that module. This was called the "attached" state.
If you tried to read from an attached word, it would fail. But if you wrote to an attached word, it would create a variable. This gave the experience of non-strict mode, without a-priori creating tons of variables.
But this creates weird words that are neither fully bound nor fully unbound. And you can't take being in the "attached" state to mean the variable does not exist in the module... because more than one attached reference to the word could have been created, and one of them might have been used to create it... not knowing about the other word's attached state to fix it up. Or perhaps the variable was created explicitly in the module--not via any particular assignment.
Should Words Be Storing "Environments"?
Historically, bound words would store the specific "address" of variables (most of the time object plus index), while unbound words would store nothing.
Attachment introduced a new situation where an "unbound" word could hold a pointer to a module, where the word would be created if a SET or SET-WORD! operation were performed.
But if objects and environments can expand, is there a good reason why the "attachment" should have been to a particular module... or should it be attached to an environment? If the specifier for a piece of code has an OBJECT! to look in first, and then a MODULE!... and a lookup doesn't find it in either, why should it become "attached" only to the module? What if it shows up in the object before you write it?
Taking this to the extreme: Why should only "unbound"/"attached" things be able to see overrides that come along later on? Why don't words store environments always, and look up every time...to be able to find new things?
Ok, Back Up.
It seems that once a word has been bound, it needs to stay bound to where it is. e.g. the following seems bad:
>> word: in [] 'foo
== foo
>> protect word ; make sure no one changes FOO's value
>> set word 10
== 10
>> some-arbitrary-routine
== <whatever> ; didn't error, so didn't try to write foo
>> get word
== 20 ; !!! it wasn't written, so how?
We'd lose some grounding if bound words weren't stable. It also would hurt performance, because words would have to be looked up in the environment chain every time.
BUT we're saying that the IN operation does this lookup, and may get different results if the environment changes. That's pretty much a given: the evaluator runs an equivalent to IN, and this is why when you run a function several times you get different bindings to different frames from the same unbound words as input.
Contain The Weirdness To "Attachment"
This points the finger at "attachment" binding being a narrow, weird thing... whose job is solely to simulate the idea that a variable exists that doesn't.
Sea of Words made it a shallow illusion, e.g. it didn't let you GET/ANY the variable and get it back as being trash--you'd get an error instead. There's risks to deepening the illusion, because you'd have to make module enumeration give back every possible word as a variable. :-/
So I think attachment should be to a module (not an environment) and it should be considered as bound for most practical purposes (it would need to be, for Rebol2 compatibility).