Why TRANSCODE Doesn't Lock Source (By Default)

I've heard it said:

"In fact, everything coming directly from the lexer should be locked." :slight_smile:

I used to agree with this (in fact, this is how Ren-C worked for a year or two). That was a good era to shore up the read-only checks, and build ways to make sure at compile-time via C++ type system that they were being honored by native code.

BUT I ultimately found myself uncomfortable with making it a hard rule. Something just got lost when you have to change:

>> x: [a b c]

>> append x 'd
== [a b c d]

To:

>> x: copy [a b c]

>> append x 'd
== [a b c d]

It seems small. But Rebol is about the avoidance of small things. Like parentheses when you don't want them... sure you COULD be forced to add them, it would reduce some risks, but it's left as a choice.

I think here this is another example of one of those small choices that adds up. You're using the word COPY you don't necessarily want to use or see. You're making a copy you don't necessarily want to pay for. Saying you can't do that without the copy felt like it was a drift from the premises that make Rebol be Rebol.

So eventually I was swayed to believe this should be a choice. The script or module header should be able to say "I want this transcoded frozen" or "I want it left mutable". Right now it chooses the liberal default, and I feel like it's the right choice.

The way I protected people from themselves is CONST; and when you have something like the execution of a function body, or a loop body, that const Cell bit trickles down (as with the binding).

https://rebol.metaeducation.com/t/value-vs-series-modification-bit-const-and-mutable/976

It's worth emphasizing:

If CONST did not exist, the risks of mutable-by-default source would be too great.

I would still come down on the side of always locking transcoded material from being modified.

Once CONST came on the scene, it allows that "you get what you pay for" kind of feeling.

  • You get the casual interactivity in the console or test scripts you want

  • If you have global blocks or strings in a script of which there is only a single instance you don't have to ritually create two instances.

I've become satisfied with it, and with mutability still being the default mode. In practice I haven't had any bugs of the classic form where you forget to copy, because all the cases that need to be
covered are covered.