REBOL Technologies

Value return after computation

Carl Sassenrath, CTO
REBOL Technologies
25-Jun-2007 17:34 GMT

Article #0338
Main page || Index || Prior Article [0337] || Next Article [0339] || 15 Comments || Send feedback

There is a simple and general pattern in code that takes this form:

a: do [b: c d b]

We want the value of c (the first expression) returned, not d (the second) so we must use b as a temporary in order to return it.

For example:

rev: func [str /local tmp] [
    tmp: copy str
    reverse str
    tmp
]

This code seems longer than we need. We'd prefer to write:

a: c d

but, of course, that returns d and not c.

Stated in English it is "return the result of the first computation". We want to follow the return value with a function that is not to be computed but not returned.

We could invent a function that evaluates c and d but returns c:

a: follow [c d]

The follow function could be defined as:

follow: func [blk] [first reduce blk]

(Another possible name might be after. But, let's just use follow for right now and think about the name later.)

Now, the above example becomes:

rev: func [str] [
    follow [
        copy str
        reverse str
    ]
]

Of course, there is additional overhead in that approach: an extra function call and a block reduction. An alternative is:

rev: func [str] [
    follow copy str reverse str
]

This form can be defined as:

follow: func [a b] [:a]

There has also been a suggestion to add an /after refinement to return. For example:

rev: func [str] [
    return/after copy str reverse str
]

This is trivial to implement, but it is only effective for function return cases, not the general pattern. But, maybe the function return case is the most common.

If you have ideas or insights, I welcome you to post a comment.

15 Comments

Updated 10-Mar-2024   -   Copyright Carl Sassenrath   -   WWW.REBOL.COM   -   Edit   -   Blogger Source Code