I mentioned that the @ types were slated for use for literal matching. The most frequent example I have given is:
>> block: [some "a"]
>> uparse [[some "a"] [some "a"]] [some @block]
== [some "a"] ; success gives result of last matching rule
Works with all types:
>> num: 1
>> uparse [1 1 1] [some @num]
== 1
I didn't mention things like @(gr o up) but those work too:
>> uparse [1 1 1] [some @(3 - 2)]
== 1
I realized I actually do not know how to write the above two cases in Red or Rebol2. You can't use the number as a plain variable in Red, since it acts as a repeat rule (UPARSE prohibits that, since it's a rule that takes an argument, you must use REPEAT for such behavior)
red>> num: 1
red>> parse [1 1 1] [some num]
*** Script Error: PARSE - invalid rule or usage of rule: 1
Also in Red, I'm not clear on why the following isn't an error, since the GROUP! product is just discarded:
red>> parse [1 1 1] [some (3 - 2)]
== false
This is something that would work in R3-Alpha, but doesn't in Red or Rebol2:
red>> parse [1 1 1] [some quote (3 - 2)]
== false
Your guess is as good as mine. Whatever the answer in their world is, it's not obvious. But I think the @ types give a clean answer in UPARSE.
But What About @[bl o ck] ?
We might say that it means match a block literally:
>> uparse [[some "a"] [some "a"]] [some @[some "a"]]
== [some "a"]
This seemed a bit wasteful, since we already have a way to match blocks literally by quoting them:
>> uparse [[some "a"] [some "a"]] [some '[some "a"]]
== [some "a"]
But UPARSE has changed the game for why @[...] and [...] can mean different things...because block rules synthesize values. And who's to say you might not want to match a rule and use its product as the literal thing to match against?
>> uparse [1 1 1 2] [@[some '10, (10 + 10) | some '1 (1 + 1)]]
== 2
In other words your rule can match and provide an answer for the thing to match next. We have zero experience with how often that might be useful, but maybe it is?
Lone @ For Quoting Next Item Literally
I've defined @ to synthesize the value after it:
>> uparse "a" [collect [keep @ keep, keep <any>]]
== [keep "a"]
So it's acting like this:
>> uparse "a" [collect [keep ('keep), keep <any>]]
== [keep "a"]
This can be helpful when you're trying to build a rule with COMPOSE and the contention over GROUP! and trying to nest inside of it becomes a bummer.
As an example, let's say you're trying to build a KEEP parse rule inside a parse rule (which I am actually at this moment trying to do in the whitespace interpreter project):
name: "Binky"
uparse ... [... collect [
keep (compose [keep (to word! name)])
] ...]
Okay so that gives you [keep Binky]. Not what you wanted since it will give an error that Binky is not defined. You can quote it...
keep (compose [keep '(to word! name)])
Now you've got [keep 'Binky]. But you're not trying to match Binky in the input, you're trying to synthesize it out of thin air. Imagine we need it in a GROUP!... let's just go ahead and use the wacky engroup operator to do that:
keep (compose [keep (engroup quote to word! name)])
So we got our [keep ('Binky)]... but that was annoying.
Since @ can literally synthesize a value without matching in parse, we can make something less head-scratchy:
keep (compose [keep @ (to word! name)])
And that gives us [keep @ Binky] which is much nicer. The key to seeing why this breaks us out of the problem is that it lets us get at literal values without a GROUP!, which means we aren't trying to COMPOSE inside of COMPOSE groups.