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 records have constructors having parameters with default value? #3164

Closed
Cat-sushi opened this issue Jun 23, 2023 · 4 comments
Closed
Labels
feature Proposed language feature that solves one or more problems

Comments

@Cat-sushi
Copy link

The comment of #2364 shows examples of primary constructors having parameters with default values.

I think constructors of records are primary constructors, essentially, but they don't have them.
Are there any good reasons why constructors of records don't have parameters with default value?

@Cat-sushi Cat-sushi added the feature Proposed language feature that solves one or more problems label Jun 23, 2023
@Cat-sushi
Copy link
Author

Default values are not parts of a type of function.
Is this the reason?

@eernstg
Copy link
Member

eernstg commented Jun 23, 2023

If something like #3040 (in particular, the 'static extensions' part) is accepted into Dart then we could do something. The first problem is that record types are structural, and hence there is no unique name for them; but we could use a type alias to associate a name with a given record type:

typedef MyRecord<X, Y> = (X, {Y y});

static extension MyRecordConstructors<X> on MyRecord<X, String> {
  factory MyRecord(X x, {String y = 'foo'}) => (x, y: y);
}

void main() {
  var r = MyRecord(1); // Uses default value to get `y: 'foo'`.
}

I don't think constructors of records need to be considered as primary constructors. As proposed in #3023, a primary constructor is nothing other than an abbreviated syntax for a declaration of a completely normal, generative constructor. In the approach shown above, we are also just using completely normal formal parameter mechanisms to declare positional and named parameters, and providing a default value for some optional parameters. Nothing new here, it's just a matter of being able to use well-known things on a new kind of type.

@Vedsaga
Copy link

Vedsaga commented Dec 5, 2023

It would be useful to let set default value to record, or may be if we can let the default value for the named record elements to be optional if marked nullable ( similar to Class)

Currently things quickly gets complicated... Sometimes it feels to ideally have class itself instead... As in below code can be seen need to reduently pass the null value...

 ({
    bool? isProcessing,
    bool? isValidInput,
    bool? isImageSelected,
    bool? isInterestsSelected,
    bool? isStageTwoCompleted,
    io.File? imageFile,
  })? _mapStateToButtonProperties(OnboardingState state) {
    // Implement logic to map state to button properties like isStageOne,
    //isProcessing, etc. Return a tuple or a custom object
    // containing these properties
    return switch (state) {
      OnboardingInitial() => null,
      OnboardingProfileInput() => (
          isProcessing: null,
          isValidInput: null,
          isImageSelected: null,
          isInterestsSelected: null,
          isStageTwoCompleted: null,
          imageFile: null
        ),
      ValidOnboardingProfileInput() => (
          isProcessing: null,
          isValidInput: true,
          isImageSelected: null,
          isInterestsSelected: null,
          isStageTwoCompleted: null,
          imageFile: null
        ),
      SavingOnBoardingProfileData() => (
          isProcessing: true,
          isValidInput: null,
          isImageSelected: null,
          isInterestsSelected: null,
          isStageTwoCompleted: null,
          imageFile: null
        ),
      FailedToSaveOnBoardingProfileData() => null,
      DuplicateUsernameError() => null,
      CheckingOnboardingProfileData() => null,
      OnboardingStageOneComplete() => (
          isProcessing: null,
          isValidInput: null,
          isImageSelected: null,
          isInterestsSelected: null,
          isStageTwoCompleted: null,
          imageFile: null
        ),
      OnboardingStageTwoComplete() => (
          isProcessing: null,
          isValidInput: null,
          isImageSelected: state.uploadedPhoto != null,
          isInterestsSelected: null,
          isStageTwoCompleted: true,
          imageFile: null
        ),
      OnboardingStageThreeComplete() => null,
      FailedToFetchDocument() => null,
      NoProfileFound() => null,
      OnboardingInvalidUserID() => null,
      RestoredOnboardingProfileInput() => null,
      InitialOnboardingProfileInput() => null,
      ProfilePhotoFileSelectedState() => (
          isProcessing: null,
          isValidInput: null,
          isImageSelected: true,
          isInterestsSelected: null,
          isStageTwoCompleted: null,
          imageFile: state.selectedPhoto
        ),
      OnboardingInterestsSelected() => (
          isProcessing: null,
          isValidInput: null,
          isImageSelected: null,
          isInterestsSelected: state.interests.isNotEmpty,
          isStageTwoCompleted: null,
          imageFile: null
        ),
      SavingOnboardingInterests() => (
          isProcessing: true,
          isValidInput: null,
          isImageSelected: null,
          isInterestsSelected: null,
          isStageTwoCompleted: null,
          imageFile: null
        ),
      FailedToSaveOnboardingInterests() => null,
      StartProfilePhotoUploadInOnBoarding() => null,
      InvalidProfilePhotoFileInOnBoarding() => null,
      SavingProfilePhotoInOnBoarding() => (
          isProcessing: true,
          isValidInput: null,
          isImageSelected: null,
          isInterestsSelected: null,
          isStageTwoCompleted: null,
          imageFile: null
        ),
      FailedToSaveProfilePhotoInOnBoarding() => null,
      UpdatingUserPref() => null,
      FailedToUpdateUserPref() => null,
      UpdateUserPrefSuccess() => null,
    };
  }

@munificent
Copy link
Member

munificent commented Mar 11, 2024

Sometimes it feels to ideally have class itself instead.

Yes, this is correct. :) Classes are great! There's a reason we added them to Dart first. If you have a data structure with a lot of interesting state and you want to write constructors for it... that's a class.

Records are nice too, but they aren't the solution to all problems.

I don't think it makes sense for records to have default values. Default values are a property of function declarations, not types, and there are no function declarations for records, so I'm going to close this issue.

@munificent munificent closed this as not planned Won't fix, can't repro, duplicate, stale Mar 11, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature Proposed language feature that solves one or more problems
Projects
None yet
Development

No branches or pull requests

4 participants