Interface and implementation of this replacement for Rebol/Red REJOIN This is a draft implementation of a function called COMBINE.  It's not intended to be a complex formatting dialect, just a replacement for REJOIN that has a better name and more useful behavior.  Its purpose is laid out pretty thoroughly in this blog entry:

http://blog.hostilefork.com/combine-alternative-rebol-red-rejoin/

But to make a long story short, it is supposed to let you flatten expressions into a string.  If an expression returns a block, then that block will be recursively evaluated using the same rules as if it had been handed to COMBINE directly:

combine: function [
    {Combine evaluated expressions and substitute block variables to produce a string}
    block [block!] "Specification to process"
    /with "Add delimiter between values (will be combined if a block)"
        delimiter [block! any-string! char!]
    /into "Insert output into an existing string instead of making a new one"
        out [any-string!]
    /local
        value
] [
    ;-- No good heuristic for string size yet
    unless into [
        out: make string! 10
    ]

    if block? delimiter [
        delimiter: combine delimiter
    ]

    needs-delimiter: false
    pre-delimit: does [
        either needs-delimiter [
            out: append out delimiter
        ] [
            needs-delimiter: true? with
        ]
    ]

    ;-- Do evaluation of the block until a non-none evaluation result
    ;-- is found... or the end of the input is reached.
    while [not tail? block] [
        set/any 'value do/next block 'block

        ;-- Blocks are substituted in evaluation, like the recursive nature
        ;-- of parse rules.

        case [
            unset? :value [
                ;-- Ignore unset? (precedent: any, all, compose)
            ]

            none? :value [
                ;-- Skip all nones
            ]

            any [
                function? :value
                closure? :value
            ] [
                throw make error! "Evaluation in COMBINE gave function/closure"
            ]

            block? value [
                pre-delimit
                out: combine/into value out
            ]

            any-block? value [
                ;-- all other block types as *results* of evaluations throw
                ;-- errors for the moment.  (It's legal to use PAREN! in the
                ;-- COMBINE, but a function invocation that returns a PAREN!
                ;-- will not recursively iterate the way BLOCK! does) 
                throw make error! "Evaluation in COMBINE gave non-block! block"
            ]

            any-word? value [
                ;-- currently we throw errors on words if that's what an
                ;-- evaluation produces.  Theoretically these could be
                ;-- given behaviors in the dialect, but the potential for
                ;-- bugs probably outweighs the value (of converting implicitly
                ;-- to a string or trying to run an evaluation of a non-block)
                throw make error! "Evaluation in COMBINE gave symbolic word"
            ]

            true [
                pre-delimit
                out: append out (form :value)
            ]
        ]
    ]
    either into [out] [head out]
]


Pretty much anything here is up for review; both the interface and the implementation.  A few things to wonder about:


What would be a good heuristic for the output size?
Right now combine [if (1 &gt; 2) {something}] returns an empty string.  Initially I thought that if it only received NONE, then it should return NONE.  But the existence of the /INTO refinement makes that not possible to distinguish, as it's supposed to return the insertion position.  Is this distinction more important than offering /INTO to the caller (rejoin didn't...).
How should other string types be returned?  Currently the only way to get a non-string is to use /into, in order to avoid the sensitivity of the type of the first element that REJOIN has.  But should there be an /AS refinement for passing the target type?
Some thoughts:

Initialize String

unless into [
    out: make string! 10
]


Don't know how else to discern the initial string allocation, perhaps just start with zero?

OUT might be a strange word for a value that is both input and output. I'd also allow a NONE! value here.

/input out [any-string! none!]


Then you can initialize like:

out: any [out make string! 0]


Delimiter

if block? delimiter [
    delimiter: combine delimiter
]


Cool, a delimiter can be combined on the fly!

needs-delimiter: false
pre-delimit: does [
    either needs-delimiter [
        out: append out delimiter
    ] [
        needs-delimiter: true? with
    ]
]


Rather than an extra function and an extra value for this, why not just an extra value:

active-delimiter: none


Then set active-delimiter to delimiter after the first step through BLOCK.

Iteration

while [not tail? block] [
    set/any 'value do/next block 'block
    ...
]


I'm not certain about this, but I believe FOREACH is faster than WHILE. This seems like an inefficient way of expressing:

foreach value reduce block [
    ...
]


Functions

function? :value
closure? :value


Are you just testing for these two types of function? Otherwise ANY-FUNCTION? would catch both.

Throwing Errors

throw make error! "Evaluation in COMBINE gave function/closure"


I don't think this works in Rebol 3, at least not without wrapping the function call in a CATCH block. As I understand it, you need to DO an error to trigger it.

Coerce Output Type

An /AS refinement might be a good way to do this, so long as the type is with the ANY-STRING! typeset. It'd be a close call as to whether /INTO or /AS would take precedence for output type:

type: any [type string!]
out: any [out make type 0]


None/Empty

My opinion here is:

combine []
combine [none]


Should return ""

combine/with [none none] ","


Should return ","