DIP 1019--Named Arguments Lite--Community Review Round 2

Jacob Carlborg doob at me.com
Fri Jun 7 18:23:52 UTC 2019


On 2019-06-06 22:04, Walter Bright wrote:
> I'll reiterate what I wrote for DIP1020 
> https://digitalmars.com/d/archives/digitalmars/D/DIP_1020--Named_Parameters--Community_Review_Round_1_325299.html#N325627 
> 
> 
> ---
> 
> Here's a much simpler proposal, based on the recognition that D already has
> named parameters:
> 
>     https://dlang.org/spec/struct.html#static_struct_init
> 
> and related:
> 
>     https://dlang.org/spec/hash-map.html#static_initialization
>     https://dlang.org/spec/arrays.html#static-init-static
> 
> The only additional syntax would be allowing the equivalent of
> https://dlang.org/spec/hash-map.html#static_initialization in the argument
> list.
> Assignment of arguments to parameters would work the same way as 
> assignments to
> fields.

Related https://github.com/dlang/DIPs/pull/71.

> As for the semantics, given this constraint, nothing needs to be 
> invented, just
> discovered as necessary behavior. Consider:
> 
>      void snoopy(T t, int i, S s);     // A
>      void snoopy(S s, int i = 0; T t); // B
> 
> and calling it:
> 
>      S s; T t; int i;
>      snoopy(t, i, s); // A
>      snoopy(s, i, t); // B
>      snoopy(s, t); // error, neither A nor B match
>      snoopy(t, s); // error, neither A nor B match
>      snoopy(s:s, t:t, i:i); // error, ambiguous
>      snoopy(s:s, t:t); // B
>      snoopy(t:t, s:s); // B
>      snoopy(t:t, i, s:s); // A
>      snoopy(s:s, t:t, i); // A
> 
> I.e. function resolution is done by constructing an argument list 
> separately
> for
> each function before testing it for matching. Of course, if the parameter
> name(s) don't match, the function doesn't match. If a parameter has no
> corresponding argument, and no default value, then the function doesn't 
> match.
> 
> I don't see much point in requiring the names, preventing use of names, nor
> aliasing them. This has never been an issue for struct initializers.
> 
> One nice thing about this is the { } struct initialization syntax can be
> deprecated, as S(a:1, b:2) can replace it, and would be interchangeable 
> with
> constructor syntax, making for a nice unification. (Like was done for array
> initialization.)
> 
> One issue would be order of evaluation: would the arguments be evaluated 
> in the
> lexical order of the arguments, or the lexical order of the parameters?
> 
> Rationale:
> 
> Although this supports reordering, the real reason for naming is so one can
> have
> a function with a longish list of parameters, each with a reasonable 
> default,
> and the user need only supply the arguments that matter for his use 
> case. This
> is much more flexible than the current method of putting all the 
> defaults at
> the
> end of the parameter list, and defaulting one means all the rest get 
> defaulted.
> 
> A secondary reason is (again) for a longish list of parameters, when the 
> user
> finds himself counting parameters to ensure they line up, then named 
> parameters
> can be most helpful.

This is similar to how it works in Ruby:

foo({ "asd" => 3 }) # pass a hash (associative array) to "foo"

It's also common to pass a symbol instead of a string when the valid 
keys are few:

foo({ :asd => 3 })

In a function call, when passing a hash, it's possible to drop the curly 
braces:

foo(:asd => 3)

In Ruby 1.9 they added syntax sugar constructing hashes with symbols as 
the keys:

foo({ asd: 3 })

Combining that with the possibility to drop the curly braces you 
basically get named arguments:

foo(asd: 3)

Note that in all these cases the hash corresponds to one parameter at 
the declaration site.

Then in Ruby 2.0, proper named arguments were added. This requires 
opt-in on the declaration site:

def foo(bar:, asd: 3)
end

Using the colon (:) on the declaration site requires the caller to 
supply the named arguments.

foo(1, 2) # error
foo(bar: 1, asd: 2) # ok

-- 
/Jacob Carlborg


More information about the Digitalmars-d mailing list