Enfixing ALSO, stylizing it after THEN and ELSE

As we contemplate re-stylizing operations to embrace enfix more, one kind of historically ugly construct that could use an improvement is ALSO.

Consider this line from IN-DIR:

also do block change-dir old-dir

This is a shorthand for writing:

(temp: do block, change-dir old-dir, temp)

But this can be done just fine with ELIDE (!)

(do block, elide change-dir old-dir)

So wouldn't it be more interesting if ALSO could be in the same family as THEN and ELSE, perhaps being like a THEN that doesn't modify the result?

tester: func [num] [
    switch num [
        1 [<one>]
        2 [<two>]
     ] also [
        print "It was one or two"
     ] else [
        print "It was neither one nor two"
     ]
]

>> tester 1
It was one or two
== <one>  ; the ALSO branch ran, but didn't modify the overall result

>> tester 3
It was neither one nor two

I like that it's the same number of letters as THEN and ELSE. :slight_smile:

2 Likes

The historical ALSO always plays havoc with my comprehsion, an enfix form looks far more natural to me.

2 Likes

Something a little underwhelming about ALSO in the modern world is that it's really a THEN that takes a parameter and then evaluates to that parameter.

also [...]

; same as

then x -> [... x]

It has its uses. But it's not exactly a "superpower". I use it occasionally, but it's been around for 4 years and I can't think of all that many times.

A Problem Got Me Wondering...What About A "THENELSE"?

Something I was looking at made me wonder if it could be the combined behavior of then and else:

 code: [...xxx...]

 case [...yyy...] then (code) else (code)

 ; same as

 case [...yyy...] also (code)

"Uh, what?" you might ask. "Why would you want such a thing, instead of just putting the code afterward, since it runs unconditionally?"

 case [...yyy...]
 do code

 ; or just

 case [...yyy...]
 ...xxx...

 ; wouldn't this be the same?

No, there's a twist I didn't point out which relates to error handling. THEN and ELSE don't run on every result, they specifically filter out the definitional failures.

So this means if we went with a proposal like the TRY PARSE + PARSE EXCEPT where definitional failures are used, we'd need a replacement for the THEN if you want to run on any parser success without worrying it might be NULL.

That would make it basically the complement to EXCEPT. You could then either poke your error case handling on the front with something like a TRY or on the back with an EXCEPT.

It seems a pretty good name, because ALSO suggests not really caring about what the result was.

An example from our GitLab URL adjustment

parse text [
    "http" opt "s" "://gitlab.com/"
    thru "/"  ; user name
    thru "/"  ; repository name
    opt "-/"  ; mystery thing (see remarks on CORSify-gitlab-port)
    change "blob/" ("raw/")
    to <end>
] then [
    return as url! text  ; The port will CORSIFY at a lower level
]

Today's PARSE model is that if it succeeded and tried to return NULL, that would be turned into a null isotope. It's worked out pretty well.

But if we are thinking about the model being that a mismatching parse actually RAISEs, you'd have to defuse it with something like TRY or EXCEPT or IF NOT OK? or the like. Then if the field was wide open on what PARSE could return, it could return NULL or VOID or whatever...without the isotopic tweak to stop the interaction with ELSE (and block the interaction with THEN).

In that world, then random code like the above it would sort of an accident of luck that the PARSE doesn't return NULL. Rules like TRY return NULL and succeed, and could be the overall parse result. In this case, the last rule is to <end> which will give you a series value of the end of the series...but it might be changed, even with some debug diagnostic routine right at the end.

So rewiring this in the hypothetical worldview, we'd have:

try parse text [
    "http" try "s" "://gitlab.com/"
    thru "/"  ; user name
    thru "/"  ; repository name
    try "-/"  ; mystery thing (see remarks on CORSify-gitlab-port)
    change "blob/" ("raw/")
    to <end>
] also [
    return as url! text  ; The port will CORSIFY at a lower level
]

Though that is a little bit unfortunate, as the TRY winds up suppressing errors out of the ALSO branch. Darnit. If you want to avoid that, you have to specifically throw the except in to look only at the parse result.

parse text [
    "http" try "s" "://gitlab.com/"
    thru "/"  ; user name
    thru "/"  ; repository name
    try "-/"  ; mystery thing (see remarks on CORSify-gitlab-port)
    change "blob/" ("raw/")
    to <end>
] except [
   ; do nothing
] also [
    return as url! text  ; The port will CORSIFY at a lower level
]

That's lame. :-/ Maybe there's some trick whereby you could say that since ALSO only exists as a foil to EXCEPT, that it implies suppressing raised errors. But, eh...

Either Way, I'm Open To New Ideas for ALSO

Its current behavior is certainly not bad. But I don't use it as often as I might have thought, and it's not that hard to just tunnel the result with a THEN when one wants that behavior.

I like it being in the THEN / ELSE family as an enfix construct. But is there something else even more amazing it might do?

1 Like