Fat Arrow notation with curly braces in setState Dart/Flutter

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.

Tags:

Dart

Flutter