I am very new to Dart/Flutter and I have a confusion regarding the => notation. The documentation says that the => notation is used as a shorthand to return a single expression.
bool isNoble(int atomicNumber) => _nobleGases[atomicNumber] != null;
My doubt comes when I am trying to set state in a flutter application.
RaisedButton(
onPressed: () => {
setState(() {
print('hello');
_products.add('More stuff');
})
},
child: Text('Add Product'),
),
Now when i change the setState method with => notation
RaisedButton(
onPressed: () => {
setState(() => {
print('hello'),
_products.add('More stuff'),
})
},
child: Text('Add Product'),
),
Both methods mentioned above work, that is they set the state as expected. All i had to do was change the semicolons to commas when using the fat arrow notation.
What is the logic behind this ? How is the fat arrow notation working with curly braces which contains multiple expressions within it.
Edit
As mentioned by Hemanth Raj the => returns a set and the code segment containing the => notation can be written as follows.
RaisedButton(
onPressed: () => {
setState(() {
return {
print('hello'),
_products.add('More stuff'),
};
})
},
child: Text('Add Product'),
),
How is the returned set
containing a print function and _products.add actually updating the state. Shouldn't it throw some kind of error because usually setState is done by an expression such as _products.add('More stuff');
.
This is one of the interesting questions that I would love to answer.
As the official documents say here, yes =>
is used as a shorthand syntax to { return ... }
which means =>
will just return whatever is produced on the righthand side.
Also from Dart 2.2
and above, a Set
can be defined with comma separated values enclosed in a {}
as mentioned in docs here.
Hence, the syntax you are using, i.e {}
with statements separated with a comma, it is treated as a Set
by the =>
functions. Each element being a function call, () => { f(a) , f(b), g(a),}
would return a Set
with the elements returned by each function call.
This example might help you understand what is happening under the hood:
dynamic reflect(dynamic a){
return a;
}
void main() {
Function shortHand = () => {reflect(1),reflect('a'),reflect({}),reflect([]),}; // this function when called will return a Set<dynamic>
print(shortHand().runtimeType); // will print `_LinkedHashSet<dynamic>`
}
So the syntax
() => '...'
returns a String
,
() => [ ... , ..., ...]
returns a List
and similarly () => { ... , ... , ... }
actually returns a Set
Note: This method of returning set with comma separated function calls is not recommended, would request you also not to use it unless you wanted a Set
to be returned as result
Reply to the Edit :
Let me breakdown the function call and results for you. So your code goes like this,
() => {
setState(() {
return {
print('hello'),
_products.add('More stuff'),
};
})
}
Here the =>
returns a Set
with the result of setState
, i.e it'll return { (result of setState call) }
which might be { null }
As you have call setState
the below code gets executed, which again returns a Set
with { (result of print), (result of _product.add), }
() {
return {
print('hello'),
_products.add('More stuff'),
};
}
State will update, as you are executing _products.add('More stuff')
, where 'More stuff'
will be added to _products
irrespective of where you call it. When setState
is being called, the widget will be rebuilt with the _products
with new data added.
Hope this helped!
For the record, the recommended syntax for what you are doing is:
RaisedButton(
onPressed: () {
setState(() {
print('hello');
_products.add('More stuff');
});
},
child: Text('Add Product'),
),
The syntax (args) => { statements }
is not how Dart writes function bodies, you do either (args) { statements }
or (args) => singleExpression
.
Also, you need to terminate statements with semicolons, ;
, not commas.
As others have pointed out, the syntax you use (args) => { print("something"), somethingElse }
is actually creating a set (a Set<void>
because the return type of print
is void
) and returning that.
This is a perfect storm of small syntax mistakes, which would seem reasonable to a JavaScript programmer, that comes together to actually mean something completely different in Dart. And, just to make things even worse, the code works. The set literal will evaluate its expression in order, and nobody sees the created set anyway. The syntax just doesn't generalize — you can't change any of the expressions to, say, a for-loop (yet, you will be able to in the next version of Dart).
So, in Dart, never use => {
unless you want to return a set or map.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With