How to Name the Non-Mutating Variations of Things


In Planning Ahead for BigNum Arithmetic, I proposed prefix add become mutating, while infix + become a crafty specialization that can take in a platform-sized integer and give back a “locked” integer (usually platform-sized). This would mean that despite INTEGER! being BigNum, you wouldn’t pay any performance penalty or notice a difference so long as you used + everywhere and your numbers stayed in platform integer range.

(Once your numbers started being so big as to be bignums, you might want to rethink before doing a loop that used + to add 1 over a span of a million indices, because at THAT point each + would actually have to create a whole new bignum structure in order to be non-mutating.)

But what if someone wanted the behavior of that + but wanted a prefix name for it? Well, how about PLUS. That seems to make sense, because then +: enfix :plus.

Then there could be MINUS, a similar prefix non-mutating name for the variant of the mutating SUBTRACT.

I think these names do a good job of sounding less mutating. “add” and “subtract” sound like things you do, while “plus” and “minus” sound like things that are or just happen.

I know @gchiu has suggested seeing TIMES as a loop operator, but it seems to me that would fit better as the non-mutating multiply.

>> multiply 2 3
** Error: INTEGER! source-level or locked, use TIMES instead of MULTIPLY

>> times 2 3
== 6

>> 2 * 3
== 6

But how long can this go on…?

It starts getting hazy at divide => QUOTIENT. And one wonders, does every math operation need to invent a new name for the non-mutating form? Then modulo => … MODULUS? What about integer-based DIV?

This is really a reflection of a generic problem when you have operation mutated-arg … and want to make something that’s synonymous with operation (copy mutated-arg) …, though perhaps more efficient by doing the copy as part of the operation. Basically every mutating operator in Rebol’s “mutate by default” wants a version that does this…whether it’s APPEND or UNION or LOWERCASE or anything else you can think of.

We know some languages went with mutating operations being named with an !, to warn you they changed things. So it would be append! vs append. But unsafe though it is, Rebol goes with mutation by default.

I’ve suggested that /COPY might be a good name for a refinement asking the mutating operators to copy their argument… append/copy, lowercase/copy, etc. So this convention could apply to the bignums as well… add/copy, subtract/copy. Those could still be specialized as PLUS and MINUS if it were deemed they were high-volume enough to warrant it.

But that’s a lot of typing. I suggested append+, lowercase+… as if the + was signifying you were “adding to the total number of values in the system”. This would of course look a bit strange with subtract+.

I’ve suggested also some system-level optimizations. We might be able to make append copy x y do a deferred copy, e.g. only make the copy when X gets mutated. This means the APPEND could notice that COPY X was in a copy-on-write state that hadn’t needed to do the copy yet, and hence could more efficiently create the copy-plus-space-for-y at once. Ultimately something like that may be the best option.

Impact on JOIN, REPEND, etc?

One change that I’d file under the “hasn’t been a complete win” (yet) category was the idea that JOIN take over the role of REPEND, and be the “reducing append”. Like most other such operators in the system, it would be mutating by default… meaning you had to COPY most things you’d join with (e.g. literals, join copy [%file 1 + 2 %.txt])

An idea I had at the time for the suffix for non-mutating forms would be -OF, so JOIN-OF, APPEND-OF, LOWERCASE-OF. But OF has become more interesting and nebulous, with type of x and length of x, so I don’t think that’s a good suffix to be overloading.

It may be that the best thing to do is to figure out the deferment of the copying, as a general mechanism. append copy x y or uppercase copy x seems literate enough.