Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Should parameters default to named or positional with enhanced default constructors? #1080

Open
munificent opened this issue Jul 9, 2020 · 3 comments
Labels
question Further information is requested

Comments

@munificent
Copy link
Member

The current proposal specifies that the constructor parameters are named. I've suggested a syntax that would let users choose, but even with that, we still have to pick a default for what they get if they don't write a constructor at all. I thought it would be useful to get some data, so I looked at the Flutter repo, Dart SDK repo, and the 1,000 most recent pub packages. (All of these corpora are from a few months ago because they're what I happened to have laying around. I don't expect the numbers have changed much recently.)

I looked at the parameter signatures for each constructor declaration in them and counted the number of occurrences of various combinations of parameter types. Here's the result:

Flutter:

--- Types (3734 total) ---
   2017 ( 54.017%): only named               *******************************************************
    908 ( 24.317%): only positional          *************************
    483 ( 12.935%): no params                *************
    263 (  7.043%): positional and named     ********
     33 (  0.884%): only optional            *
     30 (  0.803%): positional and optional  *
Files: 2266
Lines: 816611

Dart SDK:

--- Types (14897 total) ---
   8703 ( 58.421%): only positional          ***********************************************************
   3879 ( 26.039%): no params                ***************************
    949 (  6.370%): positional and named     *******
    647 (  4.343%): only named               *****
    494 (  3.316%): positional and optional  ****
    225 (  1.510%): only optional            **
Files: 4116
Lines: 1615758

Most recent 1,000 pub packages:

--- Types (83738 total) ---
  37572 ( 44.869%): only positional          *********************************************
  24870 ( 29.700%): only named               ******************************
  16398 ( 19.583%): no params                ********************
   2632 (  3.143%): positional and named     ****
   1770 (  2.114%): only optional            ***
    496 (  0.592%): positional and optional  *
Files: 35003
Lines: 10604548

All combined:

--- Types (102369 total) ---
  47183 ( 46.091%): only positional          ***********************************************
  27534 ( 26.897%): only named               ***************************
  20760 ( 20.280%): no params                *********************
   3844 (  3.755%): positional and named     ****
   2028 (  1.981%): only optional            **
   1020 (  0.996%): positional and optional  *
Files: 41385
Lines: 13036917

This aligns with my intuition that Flutter code leans strongly towards named parameters but other Dart code is more likely to use positional ones.

For comparison, whether an argument is passed by position or name is up to the callsite in Kotlin so the constructor you get with a data class supports both. In Swift, the default initializer you get with a struct defaults to requiring the parameters to be passed by name, which you can opt out of on a per-parameter basis. But note that named parameters are much more like keyword arguments in Smalltalk than they are like named parameters in other languages. In particular, the order is significant and the argument names are effectively part of the method "name".

In my own code, I suspect defaulting to positional would be most useful. I do used named parameters in constructors, but those tend to be in bigger more complex classes. But those are the exact classes that are likely to need a sophisticated hand-written constructor anyway.

Defaulting to positional would mean that even fields that could be optional might become mandatory if a later field needed its corresponding parameter to be mandatory.

@munificent munificent added the question Further information is requested label Jul 9, 2020
@munificent
Copy link
Member Author

cc @pq @bwilkerson since this is an example of the kind of simple ad-hoc code analysis I often do for language design stuff. :)

@leafpetersen
Copy link
Member

We have an open item to discuss the optionally named parameter proposal, is that relevant here?

@eernstg
Copy link
Member

eernstg commented Jul 10, 2020

The 'optionally named parameters' proposal is #831.

It would allow the parameters to be declared as optionally named. The parameters would then have an ordering (even though they are named) which is based on the textual declaration order, and it would be possible to pass zero or more (up to all) of the parameters by position, and the remaining ones by name.

Using required we would be able to make an arbitrary subset of the parameters optional. The required ones would have to be passed, but they could be passed by position as well as by name, it is in any case statically checked that the required parameters have been provided, and the passing style wouldn't matter.

I think the optionally named parameters would give at least a fair amount of flexibility for developers who want positional arguments for brevity with "well-known" parameters, and named arguments for rarer and/or optional ones — as well as supporting an all-positional and an all-named argument passing style.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question Further information is requested
Projects
None yet
Development

No branches or pull requests

3 participants