In thinking more about "what is MAKE", I feel like it is fundamentally a constructor.
When you think about Rebol's value proposition vs. other languages, what's the key idea?
DIALECTS. The freeform Jazz of programming.
So what should be the differentiating factor about constructors in Rebol vs. other languages?
CONSTRUCTOR DIALECTS.
When I say make my-type! [...]
then what goes in that BLOCK! needs to be delegated to MY-TYPE! in some way to allow it the freedom to interpret the hell out of that block.
And it shouldn't only be allowed to be a BLOCK! full of madness. Consistent with history where you can write things like (make block! 10)
to preallocate a size, you should be able to pass anything you want.
make my-type! 'some-word
make my-type! /some-refinement
make my-type! ${...} ; gimme a bound FENCE!
make my-type! @[...] ; special meaning if "inert" block received?
History Has Ridiculously Underformed The Potential
When you look at the TO/MAKE Matrix, it's full of meaningless choices:
rebol2>> make block! [a b c]
== [a b c]
Huh? What the hell use is that. Is it a copy? Is it a deep copy? Where's the beef?
Why isn't the constructor for block a literate landscape, subsuming the functionality of ARRAY (a terrible name for a verb) and much more?
>> make block! [4/8 initial: '*]
== [* * * *] ; length 4, capacity 8, initialize elements with *
>> make block! /8
== [] ; just capacity 8
>> make block! 4
== [~ ~ ~ ~] ; default to TRASH
There's an answer here that "dialect design is hard", and it's scary to put a dialect in the core. But there's decades of experience at this point. And maybe even ways for people to do their own rewrites and transformations so they don't have to use a make-block
function but can customize make block!
itself.
Ren-C Has Opened Up The Skies, and Will Do More
I was musing on the behavior of FENCE! in the interpreter and thought, what if it wasn't narrowly defined as being OBJECT! related. What if it was MAKE-related, with an object-generating default?
>> {x: 10, y: 20}
== #[object! x: 10 y: 20]
>> {[block!] 4/8 initial: '*} ; maybe leading block means MAKE that?
== [* * * *]
>> {block! {4/8 initial: '*}} ; maybe nesting FENCE! does it?
== [* * * *]
>> {block! 4/8 initial: '*} ; maybe starting with WORD! is enough?
== [* * * *]
>> {group!} ; synonym for -> copy '() ?
== ()
It's a half-baked thought, and I don't know what the ideal syntax is. But I feel like this could make FENCE! so much more.
So Coming Soon: The Great MAKE Purge.
In the combinatoric TO/MAKE matrix, there is a ton of garbage.
I've previously suggested that TO should not do any evaluation (e.g. be binding agnostic on what it gets in). I think that remains a good idea, that it be purely mechanical. I had some other ideas that are lingering.
I think it's time to further cull the "MAKE for the sake of thinking everything you pass needs to do something, even if it's trivial." I've been wiping out some of the garbage, but more is needed.
And we have to find a way to give users the ability to hook MAKE on their objects... such that something like make point-3D! [...]
isn't locked into a trivial extension syntax of SET-WORD! and value, but truly able to do interesting things.