What is the impact of final function parameters in Dart? - dart

I recently found out it was possible to include final in function parameters.
/// Handler for the footer leading checkbox
void _onCheck(final bool value) {
setState(() {
_checked = value;
});
}
However, this feature is not documented anywhere and it's impossible to search any information regarding this topic.
Since the value being passed to the function was already declared elsewhere and could've used var, what are the impacts of using final in function parameters?

It works like declaring any other variable as final - the variable cannot be changed after it has been initialized.
A parameter is really just a local variable where the initializing value comes from the caller instead of a local expression.
So here, you would get an error if you write value = false; in the function because value is a final variable. You would get no error if you removed the final.
Other than that, there is no difference.

Related

How to prevent getter or function from recalculate every time?

Let say I have class like this
class OrderInfo {
final String orderId;
final String status;
final DateTime orderDateTime;
final DateTime? deliverDateTime;
final String? restaurantTitle;
OrderInfo({
required this.orderId,
required this.status,
required this.orderDateTime,
required this.deliverDateTime,
required this.restaurantTitle,
});
// and a getter
Something get something {
// Very long code that I don't want to recalculate
return something;
};
}
Since all fields is final, so there's no point to recalculate (return value will be the same).
I tried create field like this.
late Something something = () {
// Very long code that I don't want to recalculate
return something;
}();
But I'm not sure this is correct way to do.
Is there other method or this is fine?
The late field is fine. I'd make it final, unless you want to allow overwriting the value.
I'd probably extract the computation function into a named helper function, like:
class OrderInfo {
late final Something something = _computeSomething();
...
Something _computeSomething() {
// Very long code that I don't want to recalculate
return something;
}
}
Keeping the computation on the side makes the variable declaration more readable, and it allows you to reuse _computeSomething if you want to, but otherwise the effect is the same.
If the Something cannot be null, you can also implement your own late variable:
class OrderInfo {
Something? _something;
...
Something get something => _something ??= _computeSomething();
...
}
The only advantage over a late final .. = ... is that it allows you to check whether the _something has been computed or not.
In some cases that's useful. Say the computation allocates a resource, and you want to release that resource later. If you just use a late variable to store the allocated value, all you can do is read that variable or not. Reading it will allocate the resource, if it wasn't already, and then you have to release it.
Using a nullable variable, you can check whether there is something to release, and do nothing if not.
In general, if you ever need to know whether a late variable has been initialized, consider not using late to begin with, because late hides the "is initialized" bit from you.
Hiding details is what makes the late final something = ...; so nice and short, so using late final is fine when you don't need to know.
(I'd generally recommend against exposing late public fields that are not final, or that do not have an initializing expression, because that will also expose a setter for the field. It either exposes the potentially uninitialize field to your users, risking it throwing when read, or it exposes a setter in your API that users cannot call anyway. A late final variable with an initializer expression is great, because it doesn't have a setter, and it is always initialized when it's read.)
save result into a final variable, then the getter only take the result, it will not recalculate :
class OrderInfo {
final String orderId;
final String status;
final DateTime orderDateTime;
final DateTime? deliverDateTime;
final String? restaurantTitle;
late final Something _somethingFinal;
OrderInfo({
required this.orderId,
required this.status,
required this.orderDateTime,
required this.deliverDateTime,
required this.restaurantTitle,
}){
_somethingFinal = _calculateSomthing();
}
// and a getter
Something get something {
// Very long code that I don't want to recalculate
return _somethingFinal;
}
Something _calculateSomthing(){
return Something();
}
}
class Something{
}

What is the right order to initialize class fields?

What is the logic here when the programmer initializes _random at once but the _streamController is initialized in the constructor?
Can all the fields be initialized without a constructor then?
RandomStore {
RandomStore() {
_streamController = StreamController<int>();
_timer = Timer.periodic(const Duration(seconds: 1),
(_) => _streamController.add(_random.nextInt(100)));
randomStream = ObservableStream(_streamController.stream);
}
late final Timer _timer;
final _random = Random();
late final StreamController<int> _streamController;
late final ObservableStream<int?> randomStream;
...
Can all the fields be initialized without a constructor ?
Yes, you can initialize all fields without having to declare a constructor, but only if you don't need a reference to the current instance (this) or if they are 'late' fields.
The determining factor in choosing where to initialize fields is whether or not you need to have the reference (even implicit) to this.
In Dart this is only available from the construcor body; this means in particular that this is not usable in the initializer list and inside the inline initializers (except for the late fields).For terminology, see Glossary below.
this is the reference to the current instance, and is required in order to read the instance fields, even if you usually omit it (e.g., in your snippet, randomStream is equivalent to this.randomStream).
For example, in your snippet, to initialize randomStream you need to be able to read the streamController field, so you have to mark it with late; thanks to late you can initialize randomStream in the constructor body or in the inline initializer (in this second case it will actually be initialized only when you try to access it for the first time; which is an advantage if its initialization is expensive and you want to avoid it as long as possible).
As an alternative to late, you could mark the field as nullable and initialize it in the constructor body (in which case the field will first be implicitly initialized with a null value; in fact this approach is not usable if the field is final and therefore cannot be reassigned).
Instead, to initialize the streamController field, you don't use a reference to this, so you could avoid the overhead of marking the field with late and you can initialize it in the initializer list or in the inline initializer (it is the same).
Example:
class RandomStore {
final StreamController<int> _streamController;
RandomStore()
: _streamController = StreamController<int>() {
}
}
Is late always a good choice? (UPDATED)
While from the above it might seem that 'late' is a great solution for most situations, the doc suggests avoiding 'late' if it is not really necessary, because:
It is less secure:
a late field (also if it has a non-nullable type) entails a risk of errors at runtime similar to that which occurred before the introduction of sound null safety, because Dart does not force you to perform any checks before reading its value (unlike nullable fields, for which access to properties requires the use of not null operator or conditional operator). Note that Dart does not offer the possibility to check if a late field has already been initialized (See Issue #324 mentioned below)
It adds overhead:
under the cover will be created a field with the indicated type, a field -presumably boolean- for keep track of whether the initialization has occurred, and a getter that at each access checks if the initialization had occurred.
Useful sources about late:
Doc Guide about null safety and late variables https://dart.dev/null-safety/understanding-null-safety#late-variables
Dart Best practice about late
https://dart.dev/guides/language/effective-dart/usage#dont-use-late-when-a-constructor-initializer-list-will-do
https://dart.dev/guides/language/effective-dart/usage#avoid-late-variables-if-you-need-to-check-whether-they-are-initialized
Dart issue #324 Should we provide a way to query the status of late variables?
a very interesting insight into 'late' (the discussion in which the Dart Team decided not to allow the final developers to check if a late field has been initialized)
Note the differences with Java:
(which personally made it difficult for me to switch from Java to Dart at first)
this in Dart is not available in inline initializers (in Java it is available)
the final fields in Dart must be initialized before the constructor body (in Java they can also be initialized in the constructor body)
Gloassary:
class MyClass {
MyClass(String v1, String v2)
: myField1 = v1, myField2 = v2 //This is the "initializer list"
//Compared to inline initializers, it allows you to initialize fields using the constructor arguments
{
//This is the "constructor body"
myField4 = myField1; //This operation require an implicit reference to `this`; it is equivalent to `myField4 = this.myField1;`
}
String myField1;
String myField2;
String myField3 = '3'; //This is the "inline initialization"
late String myField4;
}

Const constructor vs. static final canonical values

As per this excellent explanation const expressions in Dart are "deeply immutable" meaning that nothing inside can ever change and therefore the entire expression will always denote the same thing. This is useful for the compiler, because it can generate the entire object graph once and re-use it every time such an expression occurs, and it is useful for the programmer to know that such an expression –even when it is deeply nested– still follows value-semantics and won't do anything behind my back.
I am using those optimizations by the compiler to use a well-structured object model (instead of hand-encoding it in a bit-vector, for example) and still get good performance. Since we can get some of those benefits also by "explicitly hashing" some values by making them run-time constants with the static final idiom, the question arises which of the two is good style to use in which case?
Consider the following example:
enum ShaftType { RING, SUN, CARRIER }
class Shaft {
final int index;
final ShaftType type;
Shaft(this.type, this.index) {
assert((type == ShaftType.CARRIER) == (index == null));
}
const Shaft.CARRIER()
: type = ShaftType.CARRIER,
index = null;
const Shaft.RING(this.index) : type = ShaftType.RING;
const Shaft.SUN(this.index) : type = ShaftType.SUN;
}
class GearPath {
final Shaft input, output, fixed;
GearPath({this.input, this.output, this.fixed}) {
// input and output must be set
assert(null != input && null != output);
// fixed shaft can't be anything else
assert(fixed != input && fixed != output);
}
GearPath.carrierToFirstRingFixedSun(int i)
: input = const Shaft.CARRIER(),
output = const Shaft.RING(0),
fixed = new Shaft.SUN(i) {}
static final singleFixedSunUp = new GearPath(
input: const Shaft.CARRIER(),
output: const Shaft.RING(0),
fixed: const Shaft.SUN(0),
);
static final directDrive = new GearPath(
input: const Shaft.CARRIER(),
output: const Shaft.CARRIER(),
fixed: null,
);
// ...
}
I can't make the main Shaft(..) and GearStage(..) constructors const because I want to check some constraints, but I can provide special-case constructors (such as Shaft.SUN(int i), Shaft.CARRIER()) which comply with those constraints (at least partially) by design and provide users legible shorthands for those common values.
On the other hand, when a const constructor would have no arguments, then I can as well write it as a static final member as I have done with GearStage.directDrive. If all users refer to this static member instead of re-creating the value again, we also get the benefit of sharing memory and fast comparisons (reference to same object). I can't declare the right-side of this definition as const, because it uses the non-const constructor, but developers can see from context that this is indeed a constant value and not global mutable singleton hidden in the static field. So for practical purposes it should be just as good as a const constructor, right?
Since I haven't found this described any where as a best practice my question is simply if this is indeed a good way to combine and trade-off between const constructors and static final "named value instances"?
Finally, I wonder if there is a way to declare GearPath.carrierToFirstRingFixedSun(int i) also as a const constructor? Currently I can't because const Shaft.SUN(i) complains about i not being constant.
(full code of example)
Dart 2 will allow you to have asserts in const constructors (as long as your condition can be computed as a const expression).
Then you will be able to write:
GearPath({this.input, this.output, this.fixed})
: // input and output must be set
assert(null != input && null != output),
// fixed shaft can't be anything else
assert(!identical(fixed, input) && !identical(fixed, output));
Until then, you can't have both validation and const expressions.
You still will not be able to make GearPath.carrierToFirstRingFixedSun(int i) const because it i is not constant. The const Shaft.SUN(i) is still not a valid const expression, even if i is the parameter of a const constructor. Each const Constructor(...) invocation must still create exactly one object, even if it occurs in the initializer list of another const constructor.
As a rule-of-thumb, you should consider whether exposing a value as const instead of final is something you want to commit to. When you make the variable const, it means that someone else can use the value in another const expression, and then changing the variable to final will be a breaking change. Saying that something is const is a commitment that you should choose deliberately, not just because you can. So, consider the use-cases of your variable. If you don't see it being used in other const expressions, then just make it final.

why does dart create closures when referencing a method?

void main() {
A one = new A(1);
A two = new A(2);
var fnRef = one.getMyId; //A closure created here
var anotherFnRef = two.getMyId; //Another closure created here
}
class A{
int _id;
A(this._id);
int getMyId(){
return _id;
}
}
According to the dart language tour page referencing methods like this creates a new closure each time. Does anyone know why it does this? I can understand creating closures when defining a method body as we can use variables in an outer scope within the method body, but when just referencing a method like above, why create the closure as the method body isn't changing so it can't use any of the variables available in that scope can it? I noticed in a previous question I asked that referencing methods like this effectively binds them to the object they were referenced from. So in the above example if we call fnRef() it will behave like one.getMyId() so is the closure used just for binding the calling context? ... I'm confused :S
UPDATE
In response to Ladicek. So does that mean that:
void main(){
var fnRef = useLotsOfMemory();
//did the closure created in the return statement close on just 'aVeryLargeObj'
//or did it close on all of the 'veryLargeObjects' thus keeping them all in memory
//at this point where they aren't needed
}
useLotsOfMemory(){
//create lots of 'veryLarge' objects
return aVeryLargeObj.doStuff;
}
Ladicek is right: accessing a method as a getter will automatically bind the method.
In response to the updated question:
No. It shouldn't keep the scope alive. Binding closures are normally implemented as if you invoked a getter of the same name:
class A{
int _id;
A(this._id);
int getMyId() => _id;
// The implicit getter for getMyId. This is not valid
// code but explains how dart2js implements it. The VM has
// probably a similar mechanism.
Function get getMyId { return () => this.getMyId(); }
}
When implemented this way you will not capture any variable that is alive in your useLotsOfMemory function.
Even if it really was allocating the closure inside the useLotsOfMemory function, it wouldn't be clear if it kept lots of memory alive.
Dart does not specify how much (or how little) is captured when a closure is created. Clearly it needs to capture at least the free variables of itself. This is the minimum. The question is thus: "how much more does it capture"?
The general consensus seems to be to capture every variable that is free in some closure. All local variables that are captured by some closure are moved into a context object and every closure that is created will just store a link to that object.
Example:
foo() {
var x = new List(1000);
var y = new List(100);
var z = new List(10);
var f = () => y; // y is free here.
// The variables y and z are free in some closure.
// The returned closure will keep both alive.
// The local x will be garbage collected.
return () => z; // z is free here.
}
I have seen Scheme implementations that only captured their own free variables (splitting the context object into independent pieces), so less is possible. However in Dart this is not a requirement and I wouldn't rely on it. For safety I would always assume that all captured variables (independent of who captures them) are kept alive. I would also make the assumption that bound closures are implemented similar to what I showed above and that they keep a strict minimum of memory alive.
That's exactly right -- the closure captures the object on which the method will be invoked.

Toggling Boolean Problem

this code is written in simple ActionScript, but i'm assuming this problem of mine would occur in all languages that have boolean datatypes.
i'm simply clicking the stage so that my boolean variable reverses its value and than traces/prints/logs it's new value. however, it's always tracing true instead of switching between true and false for each mouse click.
what am i doing wrong?
var myBool:Boolean;
stage.addEventListener(MouseEvent.CLICK, mouseClickHandler);
function mouseClickHandler(evt:MouseEvent):void
{
changeBoolean(myBool);
}
function changeBoolean(boolean:Boolean):void
{
boolean = !boolean;
trace(boolean);
}
You are passing a value to the function, not the reference. This means that boolean value inside your changeBoolean function is copied from myBool variable so when you changed it inside the function, it didn't realy change myBool variable. There are basically two solutions to this:
change the function to not accept parameters and inside it change myBool variable or
change the function so that it returns the boolean parameter and on calling the function, set the myBool valu to the result of the function
In the function changeBoolean, you're changing the value of the boolean (poor name, by the way - try to avoid naming collisions with built-in types, even with different casing) parameter. This has no effect outside that function.
You want to change the value of myBool (which I would call a class field in .Net or Java) instead.
function mouseClickHandler(evt:MouseEvent):void
{
myBool = !myBool;
trace(myBool);
}
...is what I would do (again, with a naive understanding of ActionScript).

Resources