MATCH has a fundamental safety issue:
>> match [~null~ integer!] 3
== 3
>> match [~null~ integer!] "notaninteger"
; null
>> match [~null~ integer!] null
== ???
Right now, this returns "heavy null" (e.g. ~[~null~]~
antiform). Once upon a time, heavy null was not auto-decayed when passed to functions like IF:
>> if (match [~null~ integer!] null) [print "Yes it matched!"]
** Error: IF does not accept heavy null without a ^META condition
But it came to be that for general ergonomics, heavy nulls had to decay to plain nulls when passed to normal parameters. Otherwise, they would be too invasive.
So for now, a "passing null" is conflated with a "didn't pass" signal. It will work with THEN, but be incorrect with IF.
So What To Do About MATCH and its bretheren?
Seems the alternative options are:
-
Don't worry about it. If you write match [logic!] 1 = 2 you get back a ~false~ isotope and should you write an expression like if (match [logic!] 1 = 2) [print "Match!] you get what you deserve.
-
Use a different antiform. Let's say that
match [~null~] null
is simply ~matched~ antiform. It wouldn't have the decaying property, but could have an invalidness property of not being logic testable -
Have a MATCH/FALSEY variant. Let plain match on a falsey thing trigger an error and if you write if match/falsey ... then you clearly do know what you're doing so it becomes like case (1).
-
Make all conditional arguments take ^META arguments for their conditions. This would put the responsibility for checking for antiforms on them, and they'd uniquely disallow them before UNMETA'ing them and then testing for truth/falsehood.
Option (4) is too taxing...impacting not just the interface to IF but the implementation of CASE and any conditional construct.
(3) punts the ball down the road a bit, but might not suit Chris.
Option 5. Adjust (DID ...)
as antiform-tolerant (NOT NULL? ...)
Another answer...
If you find yourself in a situation where antiforms are giving you a problem, switch to did match (or decay match, if you're trying to get the value and not test it as a condition)
I wouldn't reach for this by default. You're fine most of the time... if your MATCH doesn't contain [~null~ logic! blank!]
. It's only these quirky edge cases where it's better to let the antiforms give you a localized and clear error than wind up on a wild goose chase for why the program is acting strangely.
Beginners might be cautious and write things like did match or did parse all over the place, if they're scared of missing a case. But there's no need to write if did match integer! value, because you're testing for a value that can't possibly be false...it's an integer! or null. Experts would use it sparingly, in cases like if match typeset value, in case the typeset gets expanded into things including falsey values, when you're not fully cognizant of that happening.
This broadens the service of DID across the board, to do what it was originally intended to do: transform functions that return non-LOGIC! values and NULL as soft failure to give logic results. It can handle historical edge cases with an elegant touch, without burdening code that knows itself well enough to not hit those cases.