Imagine that we want to make the following just a little bit nicer:
; Note: this actually works in UPARSE today
let result
uparse "aaabbb" [
result: gather [
emit x: collect some ["a", keep @(<a>)]
emit y: collect some ["b", keep @(<b>)]
]
] else [
fail "Parse failed"
]
assert [result.x = [<a> <a> <a>]]
assert [result.y = [<b> <b> <b>]]
One Idea: Allow EMIT even if no GATHER is in Effect
Right now there's a little experiment which lets you do this, which assumes you meant to treat the PARSE overall as a gather vs. giving you an error that there's no GATHER:
let result: uparse "aaabbb" [
emit x: collect some ["a", keep @(<a>)]
emit y: collect some ["b", keep @(<b>)]
] else [
fail "Parse failed"
]
assert [result.x = [<a> <a> <a>]]
assert [result.y = [<b> <b> <b>]]
We could do a similar thing for COLLECT. But then we'd have to worry about what to do if you said uparse "..." [emit x: ..., keep ...] -- which was intended as a result?
While this may seem convenient, it isn't very general. It ties in a special relationship between UPARSE and GATHER, which violates some of the modularity.
I'm not thrilled about this, and would rather you made a specialization for it (GATHER-PARSE) that injected the gather above your rule block...so you were explicit about what you were doing.
Another Idea: Bring Back PARSE Return
When RETURN existed in PARSE, we could have said:
let result: uparse "aaabbb" [
return gather [
emit x: collect some ["a", keep @(<a>)]
emit y: collect some ["b", keep @(<b>)]
]
] else [
fail "Parse failed"
]
assert [result.x = [<a> <a> <a>]]
assert [result.y = [<b> <b> <b>]]
Something to think about here would be how RETURN and NULL would mix, in terms of returning null results vs. parse failures. RETURN has kind of an interesting property of rolling on to the next option if its rule fails:
>> uparse "aaa" [ return collect some "b" | return collect some "a" ] == "aaa"
But if you wanted to force a RETURN to give NULL back you could OPT it.
>> uparse "aaa" [ return opt collect some "b" | return collect some "a" ] ; null
But RETURN Was Removed in Ren-C...
I'm a little hazy on the precise complete argument for dropping RETURN...here was the commit from over 2 years ago that did it.
As a sidenote, Red's PARSE doesn't seem to have RETURN, but it doesn't seem to error either:
>> parse "" [return (10)]
== false
>> parse [10] [return integer!]
== false
I know I didn't particularly care for losing grounding on what exactly it was you were RETURN-ing from...e.g. that it wasn't the function's RETURN.
So forget RETURN. You can make it as your own combinator if you really want it...against my advice.