Enfixing ALSO, stylizing it after THEN and ELSE

#1

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 ALSO's meaning is kind of like "here's an afterthought...do it after, but don't worry about its result". Wouldn't it look better if the "announcement" that you're going to have an afterthought--the ALSO word--came after the value, instead of being mentioned before it? Something like:

do block also [change-dir old-dir]

This resembles THEN and ELSE, in that it's enfixed to take a value on the left and then run code on the right. The difference is that instead of being a "conditional", it would be an..."unconditional". THEN and ELSE are examining their left hand side, and based on it either pass that value through, or evaluate the right hand branch. Here ALSO would always execute the branch, but output what it got from the left unmodified.

A fancy illustrative chain, to show them all together:

switch x [
    1 [print "it was one"]
    2 [print "it was two"]
] then [
    print "it was either one or two"
] also [
    print "it was anything, this always runs"
] else [
    print "it was neither one nor two"
]

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

UPDATE: In the intervening time, it has been noticed that this desire is covered by ELIDE.
Hence ALSO has been re-imagined as a slightly different construct that only runs in the truthy case, but preserves its output.


Question: If ALSO becomes the infix version, what's "prefix-also" supposed to be called? THEN and ELSE are EITHER-VALUE and EITHER-VOID in their prefix form. ALSO breaks the pattern because it always evaluates its branch but never returns the branch evaluated result.

2 Likes
#2

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

Some brainstorming:

this-and-that
value-effect, value-posteffect
do-with-effect

2 Likes
#3

I don't think there's much wrong with AFTER

1 Like
#4

It was the first thing that came to mind:

 after 1 + 2 [print "hi"]

A few concerns I had were:

  • What kind of clue do you have that it's going to toss the result of the block, favoring the value it got in first? If it were called afterthought it would kind of have that clue.

  • Is AFTER too tempting a variable name? after: false | until [after] [...]

  • Even if not "variable-name-like", could AFTER have some nobler cause than "the version of ALSO people probably aren't going to use"? Is there a use for a version that doesn't throw away the result? While it may seem no more useful than just DO-ing a block, there's one twist...that today's branches get the branch condition value if they're functions.

So:

after 1 + 2 func [x] [print x | x * 10]

If AFTER was the kind of thing that always ran the branch and then returned the branch result, it would print 3 and evaluate to 30. If it was like ALSO, it would print 3, throw out the 30, and evaluate to 3.

ALSO could be an enfixed specialization of AFTER. Uh, after/thought. :stuck_out_tongue:

All that aside, it's probably fine for now just to make it the prefix ALSO and wait to see if anything more ideal comes along.

#5

Out of curiosity I checked the date, and it seems I wrote this on December 17th--which was the exact same day I posted some theorization on invisibles

That's good. Because if I had written it after the implementation of invisibles, I should have noticed they can handle this.

I've mentioned how ELIDE's desire to be entirely invisible forces its hand in evaluation order. As it's turning out, that's making it unsuitable for most all uses--except commenting things out. :scream: Hence I'm now thinking I should have biased it the other way, and made COMMENT use the "full invisible" technique, while making ELIDE a more docile operator, so you could say:

do block elide change-dir old-dir

...and it wouldn't run the ELIDE until the do block (or anything else pending on the left) had completed.

I'll mention too that because of the workings of invisibles, a DO/NEXT must consume them both. So the above call will act as a unit, just as ALSO would have...you wouldn't even need to add parentheses and it would be compatible with an arity 2 ALSO. (Really though, if that's in the middle of something, you probably want parentheses for clarity...probably wanted it for ALSO, too.)

UPDATE: DO/NEXT was re-imagined as EVALUATE, which twists the design so that it's actually possible for do block to run and complete a step, with the elide change-dir old-dir running on the next step. This helps avoid running invisibles out of turn (e.g. along with a branch that should have jumped before the invisible would execute).