As @Brett's critique of yesteryear pointed out, REJOIN sucked.
We now have much more palatable options and strategies. Most notably DELIMIT+SPACED+UNSPACED, which have become nicely defined foundations for one's daily string work.
So REJOIN is in the trash heap, but what about JOIN?
If naming were consistent, you might think from this pattern:
append a reduce b <=> repend a b
...that the following would have been true:
join a reduce b <=> rejoin a b ; one would have perhaps thought?
But no...REJOIN was single arity (and was a mess).
JOIN implicitly reduced, and was basically this:
join a b <=> append copy a reduce b
But b didn't have to be a BLOCK!, so if it was not, it wasn't reduced and just left as-is.
rebol2>> join "abc" [1 + 2 3 + 4]
== "abc37" ; so the block was reduced
rebol2>> d: 10
rebol2>> join "abc" 'd
== "abcd" ; not abc10, so the word was *not* reduced
Ren-C Drops JOIN's Implicit Reduce Semantics
Almost all of JOIN's usages turn out to be just adding one thing onto a URL! or FILE!
>> base-path: %/foo/bar/
>> filename: %something.txt
>> data: read join base-path filename
That's a good solid most of it. But Ren-C leans more heavily onto JOIN to produce PATH! and TUPLE!, because APPEND doesn't work on them.
>> item: [c d]
>> join 'a/b/ item
== a/b/[c d]
(Note that the real power tool for PATH! and TUPLE! building is COMPOSE, e.g. compose a/b/(spread block)
...but this is awkward to use in the simple appending case JOIN is serving.)
Because it's plenty legitimate to want to stick a block "as is" onto the end of a PATH! and not REDUCE it, we make JOIN fit in with APPEND and the other functions by making you be explicit when you want reducing or spreading.
>> join "abc" spread reduce [1 + 2 3 + 4]
== "abc37"
>> join "abc" spread [1 + 2 3 + 4]
== "abc1+23+4"
>> join "abc" [1 + 2 3 + 4]
** Error: Cannot JOIN blocks onto strings (use SPREAD for itemwise appending)
It's more typing, but I feel like it's the right amount of typing to be explicit about what you are doing.