Regarding The "Finality" Of FAIL, RETURN, etc.

There are some functions that by name carry a certain "finality". You don't expect there to be a way to pass them an argument that will revoke them.

For instance, it would be a bit weird if FAIL followed the BLANK-IN, NULL-OUT convention:

foo: func [error [error! blank!]] [
    fail error

    print "This looks like unreachable code."
]

Today we don't offer that Wayne's World version of "FAIL.... NOT!" So you have to write:

if error [fail error]

I've actually been in situations where repeating the error expression is complicated by things like API handle freeing issues, to where I've considered making something like MAYBE-FAIL which would be a No-Op on BLANK!... or perhaps a refinement as FAIL/MAYBE.

But I've not considered the idea of making plain FAIL a no-op on blanks. That seems wrong.

Does RETURN Have A Similar "Finality"?

I've written a bunch about how I stopped worrying and learned to love UPARSE's RETURN.

But there's something a little weird to my tastes about it being "non-final". For example:

>> uparse "aabc" [some "a" return "x" | some "a" return "b"]
== "b"  ; today's answer (also R3-Alpha's answer with PARSE)

When it reached the point of RETURN "X", there were two potential interpretations:

  1. "Okay, it's time to return! Let's see if this rule matches or not...and if not, we're returning NULL!"

  2. "It might be time to return if this rule matches. If it doesn't match, pretend we were never asked to return."

Today we have (2). It's strictly more powerful... as you can get (1) with return opt "x".

>> uparse "aabc" [some "a" return opt "x" | some "a" return opt "b"]
; null

Note also that if your RETURN value is in a GROUP! and evaluated as DO code instead of a rule, it will always succeed...and hence always final. It's only when you pass a rule that it can get revoked.

As with needing to write if error [fail error], if we switched to parse-RETURN-finality that would mean more code for opting out:

; opting out in RETURN-non-final style
uparse data [... return [your rule here] ...]

; opting out in RETURN-final style
uparse data [... result: [your rule here] return (result) ...]

But I still feel weird about RETURN in PARSE being something that can just be opted out of by the nature of its argument.

And so far, every time I've wanted to use RETURN it has been either a RETURN of a GROUP! (thus unconditional) or a RETURN OPT.

So I'm thinking of making RETURN "final"...if you give it a rule that doesn't match it returns NULL.

1 Like