I'm reminded of another thing I thought about which might help distinguish a TO from a MAKE. That could be that you are assured that TO won't evaluate anything you pass in. So if you said x: does [print "hi" 10] | to text! [x + 20], whatever did happen, it would not print out "hi" and come back as the text string "30".
That would limit what to text! of a BLOCK! would be allowed to do, e.g. to things like MOLD or FORM (but not "REMOLD" <gack!>
or "REFORM" <gaaack!>
)
As far as I know, there aren't any TOs today that break this rule. e.g. TO STRING! doesn't evaluate:
>> x: 10
>> to string! [x + 20]
== "x+20"
And even though some TOs and MAKEs fall through to each other willy-nilly, TO OBJECT! of a BLOCK! isn't one of the things that acts like the evaluating MAKE OBJECT! of a BLOCK!:
>> to object! [x: 10 + 20]
** Script Error: Cannot use to on object! value
Not being able to evaluate might help narrow down what a TO conversion still could do that's useful. For instance, to object! [...] might be like R3-Alpha's CONSTRUCT, used in loading script headers without risking doing any evaluation.
It also might suggest that so-called "construction syntax" should be sharing code with TO... not with MAKE. Consider what you get in Rebol2/R3-Alpha/Red today:
>> obj: make object! [x: quote 'foo]
== make object! [
x: 'foo
]
>> type? obj/x
== lit-word!
If you actually ran the make object!
that came back in the "molding" of the first result, you wouldn't get the same data pattern...because make object! [x: 'foo]
would evaluate to putting a WORD! in foo. to object! [x: 'foo]
could be work "as-is", and perhaps to object! [x: y:] could put the SET-WORD! of y: into the x key.
Really just a continuation of the brainstorming. Summary so far of potentially known things:
- A TO conversion won't run arbitrary code that you pass to it, or possibly A TO conversion won't even GET any variables, much less evaluate
- Every TO conversion targeting a series type performs a new allocation
- TO TEXT! 10 is "10" and TO INTEGER! "10" is 10
- A TO conversion of a value to its own datatype will do the same thing as COPY
One sort of sad-seeming part of accepting this so far is #4, which means TO TEXT! of something that is already a TEXT! would not be a mold, since COPY would not add delimiters. That sways the purpose of TO as being the mechanic the system uses for any "automatic" conversion.
I mentioned a potential invariant that APPEND of two non-matching types should be equivalent to converting and then appending. This would mean that TO BLOCK! of any atomic item would wrap it in a single element block, while TO BLOCK! of something that was already a block would just copy it and not add another outer layer. This would be different from history, which is
rebol2/r3-alpha/red> to block! "foo 10"
== [foo 10] ;-- acts as load
rebol2> to block! #foo
== [foo] ;-- hm, loading again?
rebol2> to block! <foo 10>
== [foo 10] ;-- yup, that was a good guess
red/r3-alpha> to block! #foo
== [#foo]
red/r3-alpha> to block! <foo 10>
== [<foo 10>] ;-- no LOAD here
red/r3-alpha> to block! "foo 10"
== [foo 10] ;-- okay, only loads if STRING!
This makes TO BLOCK! not too useful for one of its imagined purposes...to get a block out of something if it wasn't one already (e.g. for enumeration). So I'd suggest the TO BLOCK! of a TEXT! fall in line with putting the single element in a block. This gets that invariant that append [a b] "c" can act compatibly with append [a b] to block! "c".
Scanning strings to blocks would then be done with another operation.