Yep, they’re implemented!!! Go try them out!!!
Years ago, discussions circled around what was so special about WORD! and PATH! that they should be the only ones with LIT-XXX! forms. It seemed this was a bit that could equally apply to anything, e.g.
group: '(1 + 2).
It took a while, but eventually a general and clever solution was discovered. There’s no LIT-XXX!, just QUOTED! as a container for any type…with any level of quoting. It’s done with neat tricks!
…but what about SET-XXX and GET-XXX?
In that same vein, we might ask why PATH! and WORD! are the only types with SET-XXX! and GET-XXX! forms. Aren’t those just bits too?
GET-BLOCK! seems very useful if it would do a REDUCE in the evaluator. Instead of return reduce [x y] you could just say return :[x y]. SET-GROUP seems like it might be a little tidier too…
word: 'x set word 1020 word: 'x (word): 1020
It’s only one less character. But whether you have a preference for one or the other visually, the second can be done faster; the evaluator doesn’t have to look up SET to find the function, nor go through the trouble of filling function frames and dispatching. It’s much lighter-weight.
Yet it seems a slippery slope…
GET-BLOCK! and SET-GROUP! sure seem useful, but if we look at this as more cases of the “lit bit”, where does it stop?
If every type has a “get bit” and a “set bit”, can you have both of them? How does this mix with the LIT-XXX forms? Is there a difference between a LIT-SET-PATH! and a SET-LIT-PATH?
What would a SET-URL! look like? How are the colons mixing up with literals that have colons in them? (:15 is a TIME! in the current world…, that would become a GET-INTEGER!, so what does a GET-TIME! look like?)
This foiled ideas of the past, like trying to get rid of SET-PATH! and GET-PATH! and just say, e.g. “a SET-PATH! is one with a SET-WORD! in its last slot”. Because then to get x/1: you would need SET-INTEGER!, to get x/(y + z): you’d need SET-GROUP!, and it just seemed to go to chaos.
In the absence of a clear plan, we plodded along with the status quo, awaiting some moment of clarity.
Moment of clarity arrived: Just add BLOCK! and GROUP!
If we only allow SET and GET forms on containers, it’s a clean model (no worries about intersecting with lexical rules of the contained types). And you get your dialected parts. Need a SET-INTEGER! ? Well, you no can has. But with containers, you get it all:
my-dialect [ : "It's just as good, as `1:`, really!" :(:15) "Even better, as if you want GET-FIFTEEN-MINUTES!, you can have it..." [http://example.com/colons-legal-in-url:]: "Yup, colons are legal in URL!s" (your multi-value expression here): "goes great with expressions!" ]
Then we stop. We get 4 new parts that are genuinely useful, that make the evaluator more expressive and run common functionality faster. If you find uses in your dialects–and you almost certainly will–so much the better.
The commit for them fixes flaws in the scanner
There were some things you couldn’t make. In Rebol2/R3-Alpha/Red:
rebol2>> first [:a/(b + c)] == a/(b + c): rebol2>> first [:(a + b)/c] ** Syntax error: invalid "word-get" -- ":"
It might seem like it wouldn’t be that hard to fix, but fixing it is a lot easier if you can just pass through a moment where the head of that block is a GET-GROUP! and then twiddle it into a regular GROUP! later. (That’s how GET-PATH! works when it has a GET-WORD!-looking thing at the head). The scanner is already rather fiddly and throwing in more fiddly-bits is not forward-looking.
This lets that work basically for free, just a minor tweak on the previous method:
>> first [:(a + b)/c] == :(a + b)/c >> type of p: first [:(a + b)/c] == get-path! type of first p == group! ;-- regular GROUP! as first element of GET-PATH!, perfect
They’re awesome, you’ll love 'em
Try them out and let me know what you think, and if you find cool new dialect applications! Some demos:
; GET-BLOCK!, doing a fast REDUCE >> a: 10 >> b: 20 >> :[a b] == [10 20] ; GET-GROUP!, getting a PATH! >> o: make object! [f: 304] >> path: 'o/f >> :(path) == 304 ; SET-GROUP!, setting a BLOCK! >> m: <before> >> o: make object! [f: <before>] >> block: [m o/f] >> (block): [1020 304] >> block == [m o/f] >> m == 1020 >> o/f == 304 ; SET-BLOCK!, with a block on the right >> a: _ b: _ >> [a b]: [10 20] >> a == 10 >> b == 20 ; SET-BLOCK! with a non-block on the right >> a: _ >> b: _ >> [a b]: <thing> >> a == <thing> >> b == <thing>
I’m sure people will think of improvements, but that’s for starters.
And note they’ll get even better with mirror bytes, where (x): won’t cost any more than x: !!! I’m relatively confident I can make that happen, some groundwork is done already.