Multiple Return Values Via Infix

Note: Before multi-returns had an implementation in the C code of the evaluator, I observed they could be implemented by means of infix and skippable parameters. This was that implementation.

It's still cool to look back at just in terms of the wild things you can prototype! Post updated for modern syntax, though <skip>-able parameters no longer exist


Imagine you want to make something where it returns the sum of two values and the difference...but only the sum if you aren't using a multi-return.

/sum-and-difference: infix func [@left [<skip> set-block!] arg1 arg2] [
    let sum: arg1 + arg2  ; always returned, only calculate once
    if set? $left [
        switch length of left [
            1 [  ; we have `[x]: ...` act the same as `x: ...` 
               set left.1 sum
            ]
            2 [  ; only calculate difference for multiple returns
               set left.1 sum
               set left.2 arg1 - arg2
            ]
            fail "sum-and-difference can only return 1 or 2 values"
        ]
    ]
    return sum
]

and presto...

>> x: sum-and-difference 20 10
== 30  ; handled by plain evaluator mechanics

>> [y z]: sum-and-difference 20 10
== 30  ; handled by the infix quoting

>> y
== 30

>> z
== 10

Notice that adopts the principle that it doesn't actually try to return a BLOCK! with the multiple return values, but only the first value. But the interesting bit is that when you go about it this way, the convention is not really enforced.

What's Wrong With Doing It This Way?

A disadvantage of this technique is it means you cannot make infix functions that have multiple return values (in the sense they've already used their infixness for the purpose of the multiple return value itself).

That may or may not be bad. :-/ This offers a lot of flexibility to people for designing how their multiple return values work.

  • They could decide that blanks mean skip the assignment, so for [_ z]: sum-and-difference 20 10 it could be decided not to calculate the sum at all, and to return the difference.

    • UPDATE: The information is not available in the system multi returns to know about whether the main result was requested or not...only the additional returns. So the infix function would have this edge.
  • People who disagree with my philosophy about return the first thing could come up with their own rules...returning blocks that voidify, or maybe even the ability to mark which thing to return like [y {z}]: sum-and-difference 20 10 could calculate both but return the difference.

Telling people they are their own boss and can design multi return features however they want is a powerful idea that is a bit unnerving. Though Rebol has a lot of those. Truly a strange way of looking at multiple return value mechanics!