On 23.04.20 18:47, Gnomi wrote:
> Hi,
>
> Stephan Weinberger wrote:
>> * inherit <xyz>
> This is not that easy. It means the inherit statement then has to be parsed
> by the preprocessor instead of the compiler. Because < and > are normal LPC
> operators, they cannot be used to introduce a filename (as quotation marks
> introduce a string).
>
> I don't know, yet, what consequences this will have.
True, would need to be done in the preprocessor, which is somewhat
ugly... I think I'll go with Zesstra's proposal and use the
"inherit_file" apply; seems much cleaner and opens up many more options.
btw. now I'm wondering about the "include_file" apply, which is
obviously called before the preprocessor handles <> vs. "".
>> * default values for function arguments
> For the record:
https://mantis.ldmud.eu/mantis/view.php?id=263
>
> This also faces some interesting challenges. The implementation should
> differ: If you pass 0 explicitely, the default value shouldn't jump in.
True, didn't think about that. Too bad we don't have an undef/null -
would often make life easier...
> And you probably didn't want to stop at constants for default values,
> I guess there will be demand for expressions involving also the other
> parameters...
Limiting it to constants would be ok IMHO.
As for the syntax, see my original post. The caller would need to know
the names of course, as in any language that supports this feature.
> * How to mix positional and named arguments?
For simplicity I'd define it as 'all-or-nothing' rule: either
positional, or named.
The only useful exception might be that you can start with positional
arguments, but as soon as there is a named argument all following args
have to be named as well. This would fit the most common use case:
optional arguments. Duplicates (regardless of positional + named or
using the same name twice) throw an error.
> (For example you specify the last varargs argument as named argument
> but pass more arguments, that should go into that array, too, if it
> is an array.)
See my original post: I'd use the argument types strictly, i.e. a named
call would have to provide an array for a varargs argument. Also see the
example below.
> Forwarder (like call_other or funcall):
> * How to receive all named arguments and forward them to another function.
As a first step, apply/funcall could probably just support positional
arguments (especially because this opens up the whole new topic, that
closures would need to know argument names too). I'd start with
call_other/->.
> * How should named arguments that do not denote a specified function
> parameter be handled? (Superfluous positional arguments are discarded...)
Personally I'd like superfluous arguments to throw an error anyways, as
ignoring this silently often leads to strange bugs that are hard to
find. But I'd also be fine with the same behavior (silently ignore).
> Callee:
> * How to specify optional and non-optional named arguments?
Currently a varargs function will take any number of arguments and we
cannot specify which ones should be optional and which ones are required
- it's always "all or nothing"...
But actually a more refined 'optional' modifier would be a nice feature!
E.g.
void set_name(string name, optional string article = "a", optional
varargs string * adjectives) { ... }
-> set_name("box", "the", "small", "green");
-> set_name(name: "box", adjectives: ({"small", "blue"}));
-> set_name(article: "a", adjectives: ({"large"}), name: "box");
and - if positionals in the beginning are allowed - just:
-> set_name("box", adjectives: ({"small"}));
-> set_name(article: "the") => error: missing argument 'name'
-> set_name(article: "a", "box") => error: unnamed arguments are invalid
after named arguments
as opposed to what we have now:
varargs void set_name(string name, string article, varargs string *
adjectives) { if (!name) raise_error(...); article ||= "a"; ... }
-> set_name("box", 0, "blue", "long");
This would of course mean that an 'optional' argument would require all
following arguments to be 'optional' as well (so that positional calls
still work the same). The 'varargs' function modifier would then have
the same effect as setting all arguments 'optional'. Also, a default
value would obviously only make sense for 'optional' arguments.
> * Are all arguments passable as named arguments or only certain ones?
I don't see any benefit in having a "he who shall not be named" argument.
> * How to handle redefinitions (prototype vs. definition or inherited
> functions) that change the argument's name?
At the moment the driver doesn't care about mismatched names and just
uses the ones specified in the implementation. This is kinda strange
anyways and I'd rather have a compiler error. Same for inherited
functions; renaming arguments in an inherited object just leads to
confusion... (at least there is #pragma warn_function_inconsistent but
AFAIK this only checks the number and type of arguments).
From my experience the temptation to do this often arises exactly
*because* handling optional positional arguments is such a mess when you
don't have polymorphism (which would be a nice alternative btw.; but it
would of course be a different nightmare because of
apply/funcall/call_other which don't check the types).
> * Are there wildcard named arguments? (An argument that takes all named
> arguments that didn't match a specified parameter, similar to the varargs
> parameter for positional arguments.)
I wouldn't bother with his. The whole point of named arguments is to
make the call more explicit, so the caller has to know what arguments to
provide anyways. Hence any "automagical" handling of unknown arguments
would be counter-productive; therefore an unknown argument should just
throw an error.
Regards,
Invisible