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

Variable declaration to be 'final' by default #4117

Open
eftihis85 opened this issue Oct 2, 2024 · 17 comments
Open

Variable declaration to be 'final' by default #4117

eftihis85 opened this issue Oct 2, 2024 · 17 comments
Labels
feature Proposed language feature that solves one or more problems

Comments

@eftihis85
Copy link

eftihis85 commented Oct 2, 2024

I have observed that in my code the most variables I declare are 'final' and rarely I use some 'non final' variable declaration.

final int id = 1;
id = 2 // The final variable 'id' can only be set once.

I would propose the variables in Dart to be final by default without the keyword 'final' before the type of variable. This would save some typing.

int id = 1;
id = 2 // The final variable 'id' can only be set once.

It could be introduced the keyword 'mutable' to declare a non-final variable

mutable int id = 1;
id = 2 // Accepted

@eftihis85 eftihis85 added the feature Proposed language feature that solves one or more problems label Oct 2, 2024
@srawlins
Copy link
Member

srawlins commented Oct 2, 2024

Thanks for the request! I think this is essentially a duplicate of #136.

@hydro63
Copy link

hydro63 commented Oct 2, 2024

Not really possible, it would break pretty much all code, since you are reversing a fundemental behaviour.

PS > there is a way to fix it by analyzing the code and replacing everything correctly when migrating to new version of the language

@eftihis85
Copy link
Author

Thanks for the request! I think this is essentially a duplicate of #136.

I would say it is not the same. I am proposing to "reverse" the way we declare if a variable is mutable or not. From personal experience, the vast majority of the variables declared need to be immutable. Thus it makes sense to consider make the declaration of the immutable variables more concise, shorter and simpler.

Proposed "immutable" variable declaration:
int id = 1;

Proposed "mutable" variable declaration:
mutable int id = 1;

This is a practice that is used by functional languages and Dart has many functional characteristics.

@julemand101
Copy link

julemand101 commented Oct 3, 2024

The cost of this language suggestion are huge since it will break nearly every single project which are going to target the Dart version that includes this change. Yes, it can most likely be fixed with some automation but it is still something every project needs to do.

And when looking at the cost, it is very difficult to argue that we are gaining enough "value" for that cost we are asking all developers to put into this change.

The way Dart works here are similar to the programming languages it is inspired by like Java and C#. So it is as equally valid to have the opinion that the current way is the right way. So asking developers to make this change to their code bases while maybe also disagree with the change... that is painful.

Down vote from me.

@eftihis85
Copy link
Author

Not really possible, it would break pretty much all code, since you are reversing a fundemental behaviour.

PS > there is a way to fix it by analyzing the code and replacing everything correctly when migrating to new version of the language

I imagen that the migration process is pretty simple and safe. This is also a reply to the comment above from [julemand101].

@julemand101
Copy link

Not really possible, it would break pretty much all code, since you are reversing a fundemental behaviour.

PS > there is a way to fix it by analyzing the code and replacing everything correctly when migrating to new version of the language

I imagen that the migration process is pretty simple and safe. This is also a reply to the comment above from [julemand101].

You are still asking all projects to need run some tooling and do a commit across all their files... This is not something we have a tradition for in Dart besides null-safety which was painful for many projects even with tooling.

The value proposition does not make much sense here since current behavior are not even considered a problem that needs to be solved, to gain some developer benefit that are remotely close to the amount of work we will put on projects to be converted.

Whish issues are we trying to solve which we have today with typed variables being mutable by default?

Which patterns become more tedious with the change? E.g. for loops could become more annoying since we need to specify initial variables to be mutable.

@hydro63
Copy link

hydro63 commented Oct 3, 2024

I am for #136 proposal of adding a := operator for short final declaration, rather than completely redesigning the language to work in a way it isn't supposed to. It's short, concise, and doesn't break anything. It also follows a principle of breaking as little as possible, while still delivering a good and usable feature (very important in language design).

also while replacing everything might seem easy, there are a lot of edge cases (like final in function parameters), that make it prone to errors. it is also true that you are forcing basically every single developer to fix the problems that would occur during the migration. Solving migration bugs causes a lot of headaches, and possibly other bugs related to the mutabilty of the variable would appear.

TLDR > the := is better IMO solution for immutability, since then the final declaration is actually shorter than mutable declaration.

myFinal := 5;
var myMutable = 5;

@lrhn
Copy link
Member

lrhn commented Oct 4, 2024

Null-safety was painful because the migration could not be automated. The new feature added (nullability-)information to the language that old programs didn't have, and new programs required. The migration was to add that information to the program, correctly and consistently. (The only possible fully-automatic migration would have been to change all types to TheType? and all invocations to be prefixed by !. That would preserve the semantics, but boy would it be ugly.)

This migration would be fully automatic. No new information is added, the existing information is just represented in a different way. I don't think it's technically impossible to do this change.
But the effort, even if automated, is probably not worth it.

@eftihis85
Copy link
Author

In my opinion we should always aim to make more decluttered code. It is a benefit compounds through time but it is not measurable. I also asses that this migration can be fully automated.
The same can be done with the 'required' for the named parameters for the constructor.

@Wdestroier
Copy link

Considering I use inference most of the time, changing int id = 1; to mean final int id = 1; would not help (possibly make it worse), because I would still write either var id = 1; or final id = 1;. I agree with @hydro63, x := 1; would be a great improvement over final x = 1; (5 lessen characters). Other than that, the current language behavior is perfect.

@ykmnkmi
Copy link

ykmnkmi commented Oct 9, 2024

Some developers (me too) use final only for class and top-level library fields, not for function variables.

@Wdestroier
Copy link

Some developers (me too) use final for top-level library fields

You could write myTopField := value; instead of final myTopField = value; . That's an improvement for you too, right?

Some developers (me too) use final only for class

A class-level const modifier or an annotation implying constructors and properties are const/final would be useful, specially for Flutter widgets, but I prefer to have mutable classes when unspecified. I wonder why Dart doesn't have this feature.

Some developers (me too) do not use final for function variables.

Is the current behavior great then? You can write int x = 0; or var x = 0; and both are short enough. Changing the behavior (issue title) would require you to write extra code in the former case.

@ykmnkmi
Copy link

ykmnkmi commented Oct 9, 2024

@Wdestroier writing extra keyword is no for me; := seems more usable (thanks to Go and Python). But what about late final variables?

Some developers use final for arguments. By default, all arguments are reassignable. With this proposal, do I need to write an extra keyword for arguments?

@Wdestroier
Copy link

But what about late final variables?

The syntax would be late property := value; I guess, and the same for static. Lasse proposed this syntax in the other issue, maybe he can confirm this, but the transition looks natural.

By default, all arguments are reassignable. With this proposal, do I need to write an extra keyword for arguments?

The issue description only mentions variables, @eftihis85 would need to confirm. I think so, considering parameter values are changed less often than variables.

@hydro63
Copy link

hydro63 commented Oct 9, 2024

@ykmnkmi

But what about late final variables?

There would be absolutely no differerence compared to now. The := would only work on final assigment, not final declaration. As for final parameters, it would be possible to use := in optional and named parameters.

late final int x;
x = 5;

y := 5; // operator := is only alias for final x = expression; not late final

void func(final int arg);
void func([arg := 5]);
void func({arg := 5});

@eftihis85
Copy link
Author

The issue description only mentions variables, @eftihis85 would need to confirm. I think so, considering parameter values are changed less often than variables.

I was writing about changing the notion to declare variables. The proposal was to make all the variables to be final by default without the need to write the 'final' keyword.

Later I added a comment for the named arguments in the class constructor to be as default required without the need to write the 'required' keyword.

Some points as a response to the comments above.

  1. since the style we code nowadays is using many more times final variables then this should be the default. Without any extra key words. If change the notion := is an unnecessary solution, the same way final or required keywords are.
  2. := is good when you write, bad when you read as it is a small abbreviation. Imagine how you react when you read codem and you are tired. all these small symbols make it difficult.

@Wdestroier
Copy link

The proposal was to make all the variables to be final by default without the need to write the 'final' keyword.

The int class has a very short name, it's not the same case for most types. Longer class names (possibly including generic types), such as TreeMap<String, dynamic> map = get(...);, take too long to write/complete and are a reason to avoid writing types. Another reason is because fetch (in this example) can be changed to return another class in the future and you would need to fix each type name reference by hand. For these 2 reasons, many people would not benefit from this issue's proposed changes.

Without any extra key words. If change the notion := is an unnecessary solution,

If you're writing the type name, such as in final TreeMap<String, dynamic> map = get(...);, then you are not aiming for brevity. Why even bother with final being too long or := being too short?

the same way final or required keywords are.

The required keyword really doesn't make sense for named non-nullable arguments, for example in greet({String name}), it should be implicit. I remember seeing an issue to address the problem. Making everything final would not solve the problem, you can try this code greet({final String name}) {} in DartPad.

Imagine how you react when you read code and you are tired. all these small symbols make it difficult.

The reason why I get tired is because I need to read final over and over.

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

7 participants