[[Variadics, and naming ...]]

The title is literal--I'm really talking about ...

My proposal, which I like and @IngoHohmann liked, is that ... be a form of interactive breakpoint that triggers the debugger and lets you type in something. More or less like:

>> x: 10

>> print ["The value plus x is" ... + x]
** Encountered `...`, use RESUME/WITH to continue with value
** Debug Break

|0|>> x
== 10

>> resume/with 20
The value plus x is 30

Symbolically, it stands out a bit. And also, this would make it kind of reasonable as a sort of "TBD". If you're working on code and haven't gotten to something yet, you can indicate that pretty easily:

solve-virtual-binding: function [
    {Avoid exponential cost from nested binds}
][
    ...
]

And when people are stubbing in examples on the internet for code snippets, it's good there too. If you ever actually run the code, you'll get something more useful than an error.

But that brings up a question... ... ...

What to use for variadics?

If ... means "unfinished" or "breakpoint", it seems bad to borrow it as we are today for variadic function arguments. Currently those are with the tag <...>:

foo: function [args [integer! <...>]] [...]

Right there, juxtaposed against the coolness of the proposed usage, it seems we should pick something better, rather than blindly following along with what C and some other languages use.

So, what are the options? I actually initially used double brackets, when I wanted the system to be avoiding keywords to make it more skinnable:

foo: function [args [[integer!]]] [...]

But that's not necessarily very communicative, and looks a bit more like it's some kind of composition tool, a la composeII.

@gchiu suggests <any>, syncing up more with the PARSE sense of the word, and that might look good going before, though it might look weird doubling up with ANY-VALUE!:

foo: function [args [<any> integer!]] [...]
foo: function [args [<any> any-value!]] [...] ;-- too weird?

In a PARSE rule you can write [any any-value!], so it's not like it's that bad.

On the one hand, it's bad to make up names when CS agrees on it. So using the word <variadic> could be argued for over things like <multi> or somesuch. Then again, if the goal is to be accessible and non-intimidating then variadic and VARARGS! as the name of the type might should be reconsidered.

Either way I think <...> should be avoided, so as to let the new meaning of ... take the stage. So, ideas/votes on the fate of variadics?

I don't know a better word than ... just brainstorming: take, walk, stream, multi, lookahead, any, some, eternal, get, variadic, ...

I actually kinda like the direction get hints at.

If we want to go with symbolic over word, maybe <*> to evoke wildcarding? I dunno.

tangent -> I've been thinking about introducing "const" sooner rather than later. Basically it would be a way of saying that although a series wasn't locked, you're passing someone a "view" of that series that they can't modify through the value you've given them. As with C/C++ const, it doesn't mean the value won't change through other references, it just means if you only have a const reference then you won't be the one who changes it.

But one of the big classic questions is whether const or mutable should be the default:

Rebol has avoided the idea that APPEND! with the exclamation point mean mutable, but I still rather like the idea that <!> might mean mutable:

reverse: function [
     series [<!> any-series!]
][
    ... 
]

I guess my point there being that I sort of like the look of symbols in there, maybe even <?> instead of for <opt>...

append: function [
     series [<!> any-series!]
     value [<?> any-value!]
][
    ... 
]

Maybe ? could be null. x: ? (assuming the trick about being able to unset variables explicitly via functions that variadically left quote the left... you can't save nulls or voids in variables through ordinary set words usually)

Just thinking out loud here, wondering about the use of symbols and if <*> could make sense in a family of symbolic annotations or not. If <?> feels uneasy compared to <opt> then maybe that's a sign that these should use short words and not symbols.

+1 for const, I was thinking about it as well these days. As an added benefit, ot would be great to define object fields as const, so they can only be set from the objects methods.

I'm actually not sure I like the symbols, but maybe I would just need time.

Const series values by default may be better than actual immutable series by default.

It would take care of the bug like with routines such as func [...] [switch ... [... ["foo"]]], where the caller winds up accidentally thinking they can mutate and changing the string in the body of your switch. Today the protection for that comes from LOCK at the source level--which is somewhat heavy handed due to irreversibility, and also it doesn't have you covered when you build the function dynamically.

People might gripe if parameters defaulted const, but they can use their own function generators that adds mutable on everything. I think it's better to have to mark things mutable, then you get the information in the HELP etc. to know what changes. It's a pretty important thing.

But, again <mutable> is a very heavy word for a function spec. <update> ? <modify> (<modifies>)? <write>?

As an operator that converts const to modifiable, I think mutable being ugly is a good thing--you should think twice about using it. mutable and const operators might make the issues with source locking more palatable. If you're unhappy something is const, and you didn't put it in a MAP! or do something that absolutely required it be invariantly LOCKed, you could just mutable it if you had to.

Seven Years Later... :roll_eyes:

I've found myself considering really only two options for TBD: ... and ???

my-unfinished-function [thing [object!] other [...]] [
    register thing
    ...
    close other
]

my-unfinished-function [thing [object!] other [???]] [
    register thing
    ???
    close other
]

And I'm leaning pretty heavily toward ...

It's a novel concept to imagine taking something like "..." which is usually confined to variadics and such, letting it serve this purpose.

And I've mentioned this debug option if you hit these situations to supply the code--either permanently and editing the file (somehow?) or at the least for that session.

The fact that I use "..." in examples to mean "there's some stuff here" makes me feel like it really does belong in the meta domain.

Breaking the Variadic Status Quo

I think this is a higher calling.

While I don't think writing out <variadic> in function specs is any particular labor over ..., we could still use <...> as a TAG! and have that mean something different, though I don't know that I like that being so visually close to "unfinished thing".

One place I do find this a bit more of a loss than variadics is in PARSE

>> parse [blablah (foo bar) blablablah] [... between "(" ")" ...]
== "foo bar"

That's pretty darn nice. But we have lots of options open, like the question-mark tag or the asterisk tag:

>> parse [blablah (foo bar) blablablah] [<?> between "(" ")" <?>]
== "foo bar"

>> parse [blablah (foo bar) blablablah] [<*> between "(" ")" <*>]
== "foo bar"

Or maybe even a "something between left and right" weird tag:

>> parse [blablah (foo bar) blablablah] [<-> between "(" ")" <->]
== "foo bar"

>> parse [blablah (foo bar) blablablah] [<--> between "(" ")" <-->]
== "foo bar"

This is one of those cases where one has to think of the big picture. In isolation, the ... does look better and it seems like you're giving something up by using less visually distinct things. But that just points out how good ... is at jumping out to your perception. Using that to draw attention to unfinished code feels right to me.