Empowered by a wave of recent technical enhancements, a very, very cool change has shown how wide-open the sky is now for expression via enfix. Now you can write things like:
if block? x and (length of x = 1 + 2) [ print "x is a block of length 3" ] else [ print "x is either not a block, or not length 3" ]
That’s not some bizarre, carefully-crafted and isolated case that only works on a fluke. This is machinery clicking together after quite a lot of exploration. And there’s so much “cool” in there I almost don’t know where to start…
(UPDATE: a somewhat off-the-cuff experimental trick to try and skip expressions in “neutral” via a DON’T operator turned out to have too many drawbacks for short-circuit evaluation, sadly… hence you do really need a GROUP! or BLOCK! or something around (length of x = 1 + 2) if you’re going to short-circuit. But the rest is still true–as per the topic of this post, which is left normal enfix…which has developed over months instead of hours. )
In most ways this is strictly more powerful…since the restrained way in which operators were used before generally can still work. But in looking at the tests, I found one “casualty” of all the cool. That is that if not x = y […] gets interpreted as if (not x) = y […].
At a mechanical level, this is because changing
= to be left-enfix-normal instead of left-enfix-tight means it gives one chance at deferment. That chance is while = is sitting up next in the frame’s token pipeline, at the moment x is being filled in NOT’s frame as an argument. But when NOT doesn’t try gathering any further arguments it doesn’t rewind time and try to splice in the =… to the formerly filled argument cell. It “dampens” the deferment–NOT X goes ahead and runs.
That’s how this particular cookie bounces. Yet there’s no question this should be accepted as a casualty of the change. Reasoning:
None of the old mechanics are going away, so someone can have their own “skin” of = which is left-tight, when running in Rebol2/Red mode. This is different from past times discussing radical enfix changes–where a lot of the circumstances were about enfix becoming more “uniform” in a way that would not permit alternatives.
When discussing it before, we’ve pointed out there are probably more good options in Rebol than in other languages: if x <> y […], unless x = y […], if not (x = y) […]
I’m not even so sure that the most natural-looking interpretation of not x = y is not (x = y) in the first place. Most languages which operate on a precedence model (which this isn’t using) would say (not x) = y. That includes C…
!x == y
So given the necessity of the change, all that’s left to talk about is what more cool things to do…to help people migrate and appreciate it.
I’m definitely thinking more about ways of “sensing” code when changes happen. We might imagine a hooked NOT that can ask “hey, am I feeding my result into the left side of an equals?” and put a warning in a log. A lot of those mechanisms seem like they are part of the debugging and introspection API, or hooks into the evaluator loop itself…so I do want to be thinking about that.