When the higher-level FUNCTION code was removed, that removed the code for assigning default values to locals.
As I mentioned, it was done with GROUP!s:
/foo: function [arg1 arg2 <local> x y (1 + 2) z (null)] [...body...]
The way it worked was to augment the function's body:
/foo: function [arg1 arg2 <local> x y z] [
y: '3
z: ~null~
(...body...)
]
It evaluated the expression once, and then used a ^META of the evaluation product as the thing to assign.
Native <local>
Handling Brings Long-Desired Advantage
This theoretical advantage was not realized by the FUNCTION abstraction, as it was just injecting assignments into the body.
But now that the FUNC native is orchestrating the situation, the advantage is there.
Feature Question: Multi-Returns
When I brought up the question of [<local> word: expr]
instead of [<local> word (expr)]
, I didn't consider whether you could do multi-returns:
/bar: function [arg <local> [begin end]: (find series "a")] [...]
First of all, I'm not certain that feels like it "belongs" in the spec.
Secondly, this would require some significant redesign.
The problem is, that at the time of the spec processing, there's no object in existence to bind into and do such an evaluation.
So this would have to somehow collect the words inside the SET-BLOCK, save the expression, make the archetypal frame, bind into the archetypal frame and evaluate into its locals.
Continuing on this...
SET-WORD!s Not Being Bound Has Other Consequences
Evaluating the expression, and then writing it into a slot of a partially constructed archetypal FRAME! has other things that are ruled out:
So that can't work, because what's happening is that the expression is just being evaluated and put in a spot that represents local4. No "SET" is actually happening, because there's no completed context to assign it to.
That rules out other ideas, like assigning an "accessor".
When put this way, it makes it seem like using a GROUP! is clearer, because it makes you aware that there's no actual SET-WORD! to assign to.
Does This Suggest A Redesign Is Needed?
The system could generate the archetypal frame, with nothing in the local slots, and then bind the expressions into it and run them...just as they would run had it been an instantiated function.
So this would be a two-phase thing, that would enable things like multi-returns, accessors, weird-infix-functions that capture the thing they're assigning to in order to know their names...etc.
It's definitely a lot more than I bargained for when I suggested the feature. So what would happen here is that only a subset would be implemented, with the rest being done at a future date...
What it does point out is the set of things that the GROUP!-based syntax cannot do.
/foo: function [arg1 arg2 <local> x y (1 + 2) z (null)] [...body...]
So the big question is whether that's by design ("we don't plan to implement anything more, it's a simple low-hanging fruit you can take advantage of if it fits")... or if it's too limited.
Then... Is Freeform Dialecting Good?
It forces the question of "is the word and set-word mix good"
/foo: function [arg1 arg2 <local> x y: 1 + 2 z: null] [...body...]
Instinctually, I feel uneasy about that.
If we went that direction, I'd kind of rather have all the locals be SET-WORD!, and allow you to chain the assignments:
/foo: function [arg1 arg2 <local> x: y: z: ~] [...body...]
I think that if people were hinted that they could assign the locals there, and if they found out this gave them an efficiency boost, the feature might be taken advantage of more.
But they would not be able to be assigned in terms of arguments, so that's a limitation.
And if it's going to be limited anyway, might it be best to let people in on the limitations and just keep it as WORD! plus GROUP! ?
Leaning To: Stick With WORD! + optional GROUP!
Really, what we're talking about here is an optimization.
-
If a local wants a fixed value upon entry to the function on each call, that fixed value can be stored by the archetypal frame and copied into a new instance's cell, at the same cost that initializing it with nothing would cost.
-
If you are initializing a local in such a way, you don't have to repeat its name to initialize it... because you're putting the initial value beside it.
If the function creation process becomes two-pass, doing strange bindings/etc., you're starting to drift from the "optimizing" part of the optimization. And I'm concerned about the complexity cost of that code. Thinking about it now, there are details to where I'm not sure how it would work.
Evaluating a GROUP! and dropping its value into the slot of an incomplete archetype you're building is cheap-as-free, and not complicated.
It's a natural extension of just listing out locals as words, and I think it turns out to probably be for the best.