I've proposed changing FILE! and URL! to be more "systemically magical", that they are not strings but true proxies for the resource they represent.
But if you take something that can either be a FILE! or a TEXT!, and you think you are doing a textual manipulation with an APPEND... you could wind up writing to the file instead of adding to the string. And this is something that can happen very easily. :-/
for-each [file description] [ %some-file.dat "Random Numbers" %unimportant-file.exe "Red 0.6.4" "oops" %very-important-file.dat "Photographic Proof of Bigfoot" ][ append description " (2021)" ]
The stray "oops" caused it to get off by one. Hence instead of appending the date to the description it's corrupted your very important file!
Are Some Words Not "Alarming" Enough For Implicit I/O?
When something is in a variable and you APPEND to it, it might feel surprising to see that interacting with files and network when no "charged" word like WRITE was being used.
An annoying conclusion one would reach would be that we have to taxonomize words into those which are involved in I/O, and not have them overlap with words we use more casually for manipulation of local state.
This would suggest that the introduction of a plain APPEND port action in R3-Alpha was a mistake. It was from the wrong taxonomy, and needed to at minimum piggy-back on WRITE as WRITE/APPEND so you'd know you weren't looking at a string operation if you were reading:
write/append blackbox data
The less extreme conclusion would be that the limitation only applies to the implicit port actions.
This would draw a distinction between these two functions:
foo: func [value [port! text!]] [... append value data ...] bar: func [value [file! text!]] [... append value data ...]
The argument here would be that in the former case...the only way to get a PORT! is if you've already gone through one of the taxonomized "I/O words" such as OPEN. You've thus greenlit the idea that remote impacts will happen to that resource. You didn't know when it would happen, but you knew that wherever you passed that port off to had that approval.
But with FILE! as a casual lexical element appearing in lists, you might miss this greenlight step. So the green light has to be baked into the word itself... a word like WRITE.
Are There Other Options for "I/O Greenlighting"?
My proposal on taking the OPEN and CLOSE out of the implicit port process suggested that if you make a port out of something then every action you do on the port would be run implicitly, unless you did some kind of operation (like an OPEN or CLOSE) on that port that would batch the operations up.
This means the creation of the PORT! itself would thus serve your greenlighting act.
var: %foo.txt append (make port! var) "some data"
Some shorthand for that could be made. We could do like Haskell's notation for "putting things in the IO monad" and say that the decoration IO will MAKE PORT! on something that isn't already a port:
for-each file [%a.txt %b.txt] [ append (IO file) "some stuff" ] for-each file [%a.txt %b.txt] [ append IO file "some stuff" ]
Or you could greenlight through some parameter convention that port actions understand, like giving an @ argument:
var: %foo.txt append @var "some data" vars: [%foo.txt %bar.txt] append @(second vars) "some data"
Though I don't think I like that much...the IO concept is clearer.
Regardless, I Still Think FILE! Should Not Be An ANY-STRING!
What we're encountering here is a safety issue with implicit ports, and I think it would be an overreaction to say "don't do them at all, and let's go back to making APPEND on a file treat it like a string".
Notably the problem only applies when you're using variables or expressions. There's nothing to worry about if the argument is literally a FILE! or a URL!:
append/line %foo.txt "some data"
That feels expressive, not unsafe. The evaluator can tell the difference, and we can say that it's okay when you've given a literal path like that to accept that you know it's going to be I/O.
And I've mentioned that there are words that carry the greenlight in them... with examples like WRITE and READ:
for-each file [%a.txt %b.txt] [ write file "some stuff" ]
I feel it would be a step back to require you to decorate that. Write means write.
So... is it just a flag on a word, to say there are "IO-greenlit words" and "not-necessarily-IO words"?
Food for thought. What do you think of all this? :-/