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

For brevity, allow redirecting factory constructors to omit the formal parameter list #4135

Open
eernstg opened this issue Oct 22, 2024 · 3 comments
Labels
brevity A feature whose purpose is to enable concise syntax, typically expressible already in a longer form enhanced-syntax Used with proposals about improvements of the Dart grammar small-feature A small feature which is relatively cheap to implement.

Comments

@eernstg
Copy link
Member

eernstg commented Oct 22, 2024

This is a proposal that allows some constructor declarations to be less verbose.

The formal parameter list of a redirecting factory constructor has a certain amount of expressive power: It is possible to declare a stronger type constraint on each parameter than the corresponding parameter type in the redirectee. However, in the (very typical) case where the parameter types are the same, it is possible to compute the parameter list of this kind of constructor based solely on the redirectee.

This means that we could allow the formal parameter list to be omitted, in which case the formal parameter list would be implicitly induced, using the same parameter type for every parameter as in the redirectee.

The code would not be significantly harder to read: Documentation for a redirecting factory constructor that omits the formal parameter list could show the formal parameter list which is implicitly induced, and IDEs could show it when a mouse pointer is hovering over the constructor name.

Here is an example which is a variant of something that came out of discussions about .identifier shorthands (#357). The example is relevant simply because it declares several redirecting factory constructors.

abstract class EdgeInsetsGeometry {
  const EdgeInsetsGeometry();

  // Forward to EdgeInsets:
  const factory EdgeInsetsGeometry.fromLTRB(
    double left,
    double top,
    double right,
    double bottom,
  ) = EdgeInsets.fromLTRB;

  const factory EdgeInsetsGeometry.all(double value) = EdgeInsets.all;

  const factory EdgeInsetsGeometry.only({
    double left,
    double top,
    double right,
    double bottom,
  }) = EdgeInsets.only;

  const factory EdgeInsetsGeometry.symmetric({
    double vertical,
    double horizontal,
  }) = EdgeInsets.symmetric;

  static const zero = EdgeInsets.only();

  // Forward to EdgeInsetsDirectional:
  const factory EdgeInsetsGeometry.fromSTEB(
    double start,
    double top,
    double end,
    double bottom,
  ) = EdgeInsetsDirectional.fromSTEB;

  const factory EdgeInsetsGeometry.onlyDirectional({
    double start,
    double top,
    double end,
    double bottom,
  }) = EdgeInsetsDirectional.only;

  const factory EdgeInsetsGeometry.symmetricDirectional({
    required double horizontal,
    required double vertical,
  }) = EdgeInsetsDirectional.symmetric;

  const factory EdgeInsetsGeometry.allDirectional(double value) =
      EdgeInsetsDirectional.all;

  static const zeroDirectional = EdgeInsetsDirectional.only();
}

With the abbreviation which is proposed here, it would look as follows:

abstract class EdgeInsetsGeometry {
  const EdgeInsetsGeometry();

  // Forward to EdgeInsets:
  const factory EdgeInsetsGeometry.fromLTRB = EdgeInsets.fromLTRB;
  const factory EdgeInsetsGeometry.all = EdgeInsets.all;
  const factory EdgeInsetsGeometry.only = EdgeInsets.only;
  const factory EdgeInsetsGeometry.symmetric = EdgeInsets.symmetric;

  static const zero = EdgeInsets.only();

  // Forward to EdgeInsetsDirectional:
  const factory EdgeInsetsGeometry.fromSTEB = EdgeInsetsDirectional.fromSTEB;
  const factory EdgeInsetsGeometry.onlyDirectional = EdgeInsetsDirectional.only;
  const factory EdgeInsetsGeometry.symmetricDirectional = EdgeInsetsDirectional.symmetric;
  const factory EdgeInsetsGeometry.allDirectional = EdgeInsetsDirectional.all;

  static const zeroDirectional = EdgeInsetsDirectional.only();
}

Come to think of it, we could also allow the class name to be omitted. See #4144.

@eernstg eernstg added small-feature A small feature which is relatively cheap to implement. enhanced-syntax Used with proposals about improvements of the Dart grammar labels Oct 22, 2024
@mateusfccp
Copy link
Contributor

I tried to do this yesterday and was surprised that it doesn't just work.

@lrhn
Copy link
Member

lrhn commented Oct 22, 2024

I'm not usually a fan of omitting and inferring names, but since the "body" of a redirecting factory constructor cannot reference the parameters by name anyway, it's probably safe.
(That's a the reason I wouldn't allow an overriding instance method to omit an entire parameter list, even if it can omit the types and inherit them from the super-interface.)

The names might be copied for documentation purposes. Or not. I'd probably say that from the language's perspective, the positional parameters would be unnamed. If DartDoc or the analyzer wants to do something more, to help people, they can copy the names from the target constructor.

The grammar is trivial, it's just making the parameter list optional. If what follows the ClassName is a . identifier, it's a named constructor. If what follows that or the ClasssName is (, it's an argument list. Otherwise it's one of =>, { or =. No ambiguity possible.

(Could also allow a redirecting factory constructor to have a parameter list, and omit the types.)

@eernstg
Copy link
Member Author

eernstg commented Oct 23, 2024

(Could also allow a redirecting factory constructor to have a parameter list, and omit the types.)

(Good point! That would be very much in line with the treatment of parameter declarations in instance methods during override inference.)

@eernstg eernstg added brevity A feature whose purpose is to enable concise syntax, typically expressible already in a longer form enhanced-syntax Used with proposals about improvements of the Dart grammar and removed enhanced-syntax Used with proposals about improvements of the Dart grammar labels Oct 29, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
brevity A feature whose purpose is to enable concise syntax, typically expressible already in a longer form enhanced-syntax Used with proposals about improvements of the Dart grammar small-feature A small feature which is relatively cheap to implement.
Projects
None yet
Development

No branches or pull requests

3 participants