UPDATE: Hmmm, it seems that this feature is needed for
<static>
variables, because they need to be initialized once, hence can't be done every function run. So long as it exists for statics, we might keep it. But I will say that the question of where to put them...and the fact no one is using these... raises questions about the feature that should probably be answered.
There was a speculative feature for putting defaults in function specs, by using a GROUP!:
foo: function [
x [integer!]
/amount
y [integer!] (10)
][
x + y
]
One key concept was that if it were in the spec, then some amount of automatic documentation could be provided from it. But also it meant you could save yourself mentioning the name parameter twice, in the spec to name it and the body to default it.
But what turned out to happen is that it gets pretty much lost in the noise, when you have string-based parameter documentation. It's easy to overlook, and raises questions of whether you want any relevant evaluations in the GROUP! to run once or every time.
x: 100
foo: function [
x [integer!]
/amount
y [integer!]
{The integer to add, hey where do we put that default now?}
{Does it go before or after these documentation lines?}
(10 * x) ;-- is that relative to the parameter or to the global?
][...]
Not only that, if you want to COMPOSE function specs you run into the problem of dealing with any GROUP!s in it. So not having GROUP!s have meaning keeps you from ending up with problems with escaping there.
UPDATE: Labeled compose has pretty much solved this problem if it comes up. So I don't think it's a concern anymore.
In the meantime, we've had the pretty infix default operator come along. It gives a nice enough and unambiguous experience. You can even do your defaulting inline if you like:
foo: function [
x [integer!]
/amount
y [integer!]
][
x + y: default [10]
]
There was no particularly efficient trick for storing the values or putting them in the frame...all it was doing was putting code in the body of the function, just like having a bunch of DEFAULT lines up front. The unimplemented automatic documentation feature raises a lot of questions...if it was calculated, do you want the calculated value or just what was in the GROUP! raw? :-/
Add it all up, and the GROUP!-to-default-a-parameter looks like a turkey. So should people just learn and love DEFAULT and its good friend MAYBE, and we get rid of this?
Pursuant to my update, here's a real world example to ponder from @codebybrett's READ-DEEP:
read-deep: function [
{Return files and folders using recursive read strategy.}
root [file! url! block!]
/full
{Include root path, retains full paths vs. returning relative paths.}
/strategy
{Allows Queue building to be overridden.}
take [function!]
{TAKE next item from queue, building the queue as necessary.}
][
take: default [:read-deep-seq]
...
]
Let's imagine we want to move that default into the spec. Where?
read-deep: function [
{Return files and folders using recursive read strategy.}
root [file! url! block!]
/full
{Include root path, retains full paths vs. returning relative paths.}
/strategy
{Allows Queue building to be overridden.}
take [function!] (:read-deep-seq)
{TAKE next item from queue, building the queue as necessary.}
][
...
]
I sort of feel like it vanished into the noise. The code is shorter, but I don't feel it's clearer. Putting it on its own line is its own line seems a little weird:
read-deep: function [
{Return files and folders using recursive read strategy.}
root [file! url! block!]
/full
{Include root path, retains full paths vs. returning relative paths.}
/strategy
{Allows Queue building to be overridden.}
take [function!]
(:read-deep-seq)
{TAKE next item from queue, building the queue as necessary.}
][
...
]
If one is writing a quick-and-dirty function with less documentation, it might be clearer...people might find it expedient. This is why it works okay for <local>
s and <static>
s
read-deep: function [root /full /strategy take (:read-deep-seq)] [
...
]