The biggest realization of "modern Binding" in Ren-C was that working in a mostly unbound world needed to be the default.
What had held up early attempts to "virtualize" binding was that I was trying to automatically spread binding information in mechanical operations. e.g. when you would PICK a word out of a BLOCK!, the picked word would come back suitable to perform a GET on. It did this by projecting the virtual binding from the block onto the returned Cell.
I gave this as an example of the kind of legacy pattern I was trying to keep working:
double-assigner: func [block] [
for-each [sw i] block [
assert [(set-word? sw) (integer? i)]
set sw 2 * i ; historically assumes X: and Y: are bound
]
]
double-assigner [x: 10 y: 20]
But this makes an assumption that may not be correct...and in fact, often is not. In a world where unbound material is an effective currency, you can't guess that the user wanted the binding to be propagated. They may have just been interested in the raw material.
So this spawned the dawn of "conscious binding", where you had to use specific operations at each step:
double-assigner: func [block] [
for-each [sw i] block [
assert [(set-word? sw) (integer? i)] ; both SW and I are *unbound*
set (inside block sw) 2 * i ; <-- INSIDE BLOCK makes all the difference
]
]
double-assigner [x: 10 y: 20]
We can debate the BIND "dialect", and whether the INSIDE operator is the right one or not... but this captures the general spirit of things.
Using Our Dialect Powers...What About the TIE ($)?
So in this FOR-EACH example, we can already imagine a convenience... of being able to annotate variables to say you want to propagate the binding (or "tie" the variables to the binding of the block). How about this?
double-assigner: func [block] [
for-each [$sw i] block [
assert [(set-word? sw) (integer? i)] ; SW bound into block's context
set sw 2 * i
]
]
double-assigner [x: 10 y: 20]
That's convenient!
What If You Wanted A ^LIFT-ed Bound Variable?
There's also @PIN
-ned variables which means "reuse an existing variable, don't make a new one".
This means we need the "Sigil-Composition" that @bradrn has spoken up for. But instead of accomplishing it with BLOCK!s the way I've been doing, we now have some lighter options...
for-each [@:$sw i] block [...] ; reuse and bind
for-each [$:^sw i] block [...] ; bind and lift
for-each [^:$sw i] block [...] ; lift and bind (synonym, we assume?)
for-each [^:$:@sw i] block [...] ; lift and bind and reuse
It's not the prettiest thing in the world, but I don't imagine you'd usually need more than one Sigil.
Maybe you could put them in BLOCK!s to help visually:
for-each [[^:$:@sw] i] block [...] ; lift and bind and reuse
Did that help? It kind of did. CHAIN! seems to make the most sense... visually, and also because it doesn't really have any semantic baggage outside of trailing and leading colons. And really only trailing colons have an obvious meaning.
Would it be better if the colons weren't there?
for-each [[^ $ @sw] i] block [...] ; lift and bind and reuse
I dunno. I almost want to cluster the sigils together separate from the word:
for-each [[^:$:@ sw] i] block [...] ; lift and bind and reuse
We can debate this, but somewhere in here there will be a solution.
What About Sigil Meanings On Lists Themselves?
One of the earliest thoughts I had regarding the applications of @ as a "inert" Sigil was "what if REDUCE took this as a signal that the data was already reduced.
>> reduce [1 + 2 10 + 20]
== [20 30]
>> reduce @[1 + 2 10 + 20]
== [1 + 2 10 + 20]
That might not seem useful, but it sort of is. For instance, PACK uses this:
>> pack [1 + 2 null]
== ~['3 ~null~]~ ; anti
>> pack @[1 + 2 null]
== ~['1 '+ '2 'null]~ ; anti
This comes up, when you've got a branching structure and you have some branches that want to return evaluative products and others that you want to return a pack of literals.
So the convention spread other places, e.g. ANY and ALL where you can run predicates on data and either reduce it or not.
Could this same idea of pushing the convention onto the lists be useful... e.g. to make BLOCK!s that you "auto-bind" out of when you pick?
>> x: 10
>> tieblock: @ $[x y]
== $[x y] ; bound by the lone PIN operator (a.k.a THE)
>> tieblock: the $[x y]
== $[x y] ; bound - if you prefer words vs. symbols
>> tieblock: $ '$[x y]
== $[x y] ; bound - if you want another way to say the same thing
>> tieblock: bind here '$[x y]
== $[x y] ; bound - just for the sake of completeness...
Okay, you get the idea on the binding. But my question is: would there be operators that upon seeing a TIED! list, would automatically bind when you picked things out of them?
So instead of the binding behavior coming from the variable you were using in a FOR-EACH, it would come from the data. Or maybe even just a PICK would work:
>> pick tieblock 1
== x ; bound
>> get pick tieblock 1
== 10
So if it was an ordinary block..
>> x: 10
>> block: [x y]
>> get pick block 1
** Error: X not bound...
>> get pick tie block 1
== 10
This definitely turns Sigil-carrying entities into beasts-with-behaviors. But since the common currency in the system is normal BLOCK!/GROUP!/FENCE!, it may be that most of the creations of these beasts would be transient... existing only long enough to cue the PICK or FOR-EACH or whatever to do its behavior.
You Don't Know Until You Try... 
I'm worried about there not being some mechanical terra-firma. PICK seems foundational. So perhaps there's some difference here, e.g. between PICK and another operator like SELECT could heed the sigils on the target data (?) And FOR-EACH seems foundational too, but I think decorating the variable is fair game.
Anyway, it's an area I'll start experimenting with and report on whether any of the experiments turn out to make things clearer/better or worse. (!)