36

As stated in the dart article:

The ".." syntax invokes a method (or setter or getter) but discards the result, and returns the original receiver instead.

So I assumed that this would work:

myList..clear().addAll(otherList);

which gave me the error that I can't call .addAll on null.

So apparently . precedes .. so that .addAll has been invoked on the result of .clear().

I figure now that I have two possibilities to write this:

  1. myList..clear()..addAll(otherList);
  2. (myList..clear()).addAll(otherList); (If I wanted to get the result of .addAll().

Is this correct? If yes, why the decision to give . precedence? It seems very counterintuitive. Is it to avoid syntax like this: myList(..clear().useResultOfClear()).addAll(otherList);?

enyo
  • 16,269
  • 9
  • 56
  • 73

5 Answers5

48

As pointed in the official Dart language article Method Cascades in Dart:

The ".." syntax invokes a method (or setter or getter) but discards the result, and returns the original receiver instead.

In brief, method cascades provide a syntactic sugar for situations where the receiver of a method invocation might otherwise have to be repeated.

Below are example based/copied from the previously cited article. For further information, go read it.

add() example

In the scenario where one want to add multiple elements to a list, the legacy-way is to do multiple assignements :

myList.add("item1");
myList.add("item2");
// add again and again…
myList.add("itemN");

While you can't do something like myList.add("item1").add("item1")….add("itemN"); as the add() does not method return the myList object but a void, you can use the cascading operator instead as it discards the result, and returns the original receiver myList :

myList..add("item1")..add("item2")…..add("itemN");
myList.add("item1").add("item2")….add("itemN");

Another example

So Instead of writing:

var address = getAddress();
address.setStreet(“Elm”, “13a”);
address.city = “Carthage”;
address.state = “Eurasia”
address.zip(66666, extended: 6666);

One may write

getAddress()
 ..setStreet(“Elm”, “13a”)
 ..city = “Carthage”
 ..state = “Eurasia”
 ..zip(66666, extended: 6666);
Édouard Lopez
  • 40,270
  • 28
  • 126
  • 178
28

You can read the article from Gilad Bracha : Method Cascades in Dart. At its ends, you will see many examples.

See also this answer of Lasse Nielsen about operator precedence :

It helps to think of ".." as not really an operator, but more like a scoping construct (like parentheses). It creates a new scope from the ".." to either the next "..", or the first other scope delimiter (";", ")", "}" or similar).

Basically, a..b().c() is the same as (t){t.b().c(); return t;}(a)

Alexandre Ardhuin
  • 71,959
  • 15
  • 151
  • 132
  • You can see examples of this in the original design proposal: https://docs.google.com/document/d/1U0PeHtVQHMQ8usy7xI5Luo01W5LuWR1acN5odgu_Mtw/edit?pli=1 – Pixel Elephant Jun 10 '13 at 15:51
4

A..B().C() means calling B() on A, then calling C() based on the return value of A.B().

A..B().C()..D().E() means calling B() on A, then calling C() based on the return value of A.B(), assume it is A_B, then calling D() on A_B, i.e. A_B.D(), assume the return value of it is A_B_D, then finally do A_B_D.E().

NeoZoom.lua
  • 2,269
  • 4
  • 30
  • 64
2

From: Fu Cheng's book “Flutter Recipes” :

Dart has a special cascade operator (..) which allows us to make a sequence of operations on the same object. To chain operations on the same object in other programming languages, we usually need to create a fluent API in which each method returns the current object. The cascade operator in Dart makes this requirement unnecessary. Methods can still be chained even though they don’t return the current object. The cascade operator also supports field access.

class User {
  String name, email;
  Address address;
  void sayHi() => print('hi, $name');
}

class Address {
  String street, suburb, zipCode;
  void log() => print('Address: $street');
}

void main() {
  User()
   ..name = 'Alex'
   ..email = 'alex@example.org'
   ..address = (Address()
     ..street = 'my street'
     ..suburb = 'my suburb'
     ..zipCode = '1000'
     ..log())
   ..sayHi();
}


 
H S W
  • 6,310
  • 4
  • 25
  • 36
2

You can go through this article

Cascade operator and spread operator

class User{
  late String name;
  late String gender;
  void method()=> print("Welcome \n Name: $name \n Gender: $gender");  
}



void main(){
     User()
      ..gender = "male"
      ..name = "Shiv"
      ..method();

 }
Shiv
  • 21
  • 3