Basics

./code/hello.dart
1// run it with
2// dart ./hello.dart
3// or
4// dart run ./hello.dart
5void main() {
6  print('hello world');
7}
./code/hello2.dart
 1// run it with
 2// dart ./hello2.dart
 3// or
 4// dart run ./hello2.dart
 5void main(List<String> args) {
 6  print('args: $args');
 7}
 8/*
 9dart hello2.dart --> args: []
10dart hello2.dart a --> args: [a]
11
12Note that arg[0] is not the exe name!
13
14dart hello2.dart a bc --> args: [a, bc]
15*/

The entrypoint is the main function. It can take 0 argument or a list argument.

Note that print outputs a newline.

The help info for print can be found at https://api.dart.dev/dart-core/print.html. Note that its prototype is:

void print(Object? object)

It can print any type!

./code/test-math.dart
1// dart run ./test-math.dart
2import "dart:math" as math;
3
4void main() {
5  print(math.pi); // 3.141592653589793
6  print(math.sin(30 * math.pi / 180)); // 0.49999999
7  print(math.max(2, 3.5)); // 3.5
8}

Naming convention MyClass.myMethod(), myVariable, sourceUrl, urlDestination.

A string uses utf-16 encoding, like JavaScript. We can use either a single quote or double quotes for string literals, e.g., 'hello' and "hello" are equal.

Type of a string is String.

String interpolation is like javascript, e.g., "hello ${world}", "hello $world". We can put arbitrary expression inside ${}.

Note that String is immutable in Dart, like Python.

Doc for functions https://dart.dev/language/functions.

Doc for packages https://dart.dev/guides/packages.

num is a super class of int and double. int is 64-bit.

There is also a bool type with true and false.

String and num are subtypes of Object. All non-nullable types in Dart are subtype of Object.

Like kotlin, it has nullable types.

Collection type examples:

Two ways to create a list:

var s = <String>[];
List<String> s = [];
int? a; // default initialized to null

a ??= 3; // assign 3 to a if a is not null; else do nothing.

a = null;

int b = a ?? 10; // if a is not null, assign a to b, else assign 10 to b
./code/test1.dart
  1// run it with
  2// dart --enable-asserts ./test1.dart
  3
  4void testDouble() {
  5  // control the number of decimal points when converting it to a string
  6  double i = 2.354;
  7  assert(i.toString() == '2.354');
  8  assert(i.toStringAsPrecision(1) == '2');
  9  assert(i.toStringAsPrecision(2) == '2.4');
 10  assert(i.toStringAsPrecision(3) == '2.35');
 11  assert(i.toStringAsPrecision(4) == '2.354');
 12
 13  i = double.parse('2.32');
 14  assert(i == 2.32);
 15
 16  assert(i.ceil() == 3);
 17  assert(i.floor() == 2);
 18
 19  int a = i.toInt();
 20  assert(a == 2);
 21}
 22
 23void testInt() {
 24  int i = int.parse('23');
 25  assert(i == 23);
 26
 27  // note that i/2 is a double
 28  assert(i / 2 == 11.5);
 29  assert((i / 2) is double);
 30
 31  assert((i / 1) is double);
 32  assert((i / 1) == 23.0);
 33
 34  // truncation division: ~/
 35  assert((i ~/ 2) is int);
 36  assert((i ~/ 2) == 11);
 37
 38  // see https://api.flutter.dev/flutter/dart-core/int/tryParse.html
 39  // int.tryParse() returns null if the input is not an integer
 40  int a = int.tryParse('30a') ?? -1;
 41  assert(a == -1);
 42
 43  a = 10;
 44
 45  a += 1;
 46  assert(a == 11);
 47
 48  a -= 1;
 49  assert(a == 10);
 50
 51  // note that both ++a and a++ are valid
 52  a++;
 53  assert(a == 11);
 54
 55  ++a;
 56  assert(a == 12);
 57}
 58
 59// the type is String, not string
 60void testString() {
 61  var s = 'hello';
 62  var s2 = s + " world";
 63  assert(s2 == "hello world");
 64
 65  assert("${s} world" == s2); // string interpolation
 66  assert("$s world" == s2); //  string interpolation
 67
 68  s = '''like
 69python. multi line string
 70      ''';
 71  print(s);
 72
 73  s = """another
 74      multi-line string
 75      """;
 76  print(s);
 77
 78  String a = 'abc';
 79  assert(a.toUpperCase() == 'ABC');
 80
 81  a = 'ABC';
 82
 83  // we can print a string on assertion failure
 84  assert(a.toLowerCase() == 'abc', "${a.toLowerCase()}");
 85}
 86
 87void testBoolean() {
 88  bool a = true;
 89  assert(a);
 90  bool c = 1 == 2;
 91  assert(!c);
 92}
 93
 94void testList() {
 95  var a = [1, 2, 'a'];
 96  assert(a[0] == 1);
 97  assert(a[1] == 2);
 98  assert(a[2] == 'a');
 99  a.add(40.5);
100  assert(a[3] == 40.5);
101  print(a);
102
103  var b = List.filled(3, 0); // b's capacity is fixed, cannot be changed.
104  assert(b.length == 3);
105  assert(b[0] == 0);
106  assert(b[1] == 0);
107  assert(b[2] == 0);
108  // b.add(3); // compile time error. cannot change the size of b
109
110  var c = [1, 3, 5];
111  List<String> d = [];
112  c.forEach((i) {
113    d.add(i.toString());
114  });
115  assert(d.length == c.length);
116  assert(d[0] == c[0].toString());
117  assert(d[1] == c[1].toString());
118  assert(d[2] == c[2].toString());
119
120  // map returns an iterable; we use .toList() to convert it to a list
121  List<String> f = c.map((i) {
122    return i.toString();
123  }).toList();
124  assert(f.length == c.length);
125  assert(f[0] == d[0]);
126  assert(f[1] == d[1]);
127  assert(f[2] == d[2]);
128
129  List<int> li = [0, 1, 2, 3];
130  for (int i = 0; i != li.length; ++i) {
131    assert(i == li[i]);
132  }
133
134  for (var value in li) {
135    assert(value == li[value]);
136  }
137
138  // we can also use final if we don't change value inside the loop
139  for (final value in li) {
140    assert(value == li[value]);
141  }
142}
143
144void testList2() {
145  // type is List<String>
146  final aListOfStrings = ['one', 'two', 'three'];
147  assert(aListOfStrings is List<String>);
148  assert(aListOfStrings.isNotEmpty);
149
150  // type is Set<String>
151  final aSetOfStrings = {'one', 'two', 'three'};
152  assert(aSetOfStrings is Set<String>);
153  assert(aSetOfStrings.length == 3);
154  assert(aSetOfStrings.contains('one'));
155  assert(aSetOfStrings.contains('two'));
156  assert(aSetOfStrings.contains('three'));
157
158  // type is Map<String, int>
159  final aMapOfStringsToInts = {
160    'one': 1,
161    'two': 2,
162    'three': 3,
163  };
164  assert(aMapOfStringsToInts is Map<String, int>);
165  assert(aMapOfStringsToInts.length == 3);
166  assert(aMapOfStringsToInts['one'] == 1);
167  assert(aMapOfStringsToInts['two'] == 2);
168  assert(aMapOfStringsToInts['three'] == 3);
169
170  final aListOfInt = <int>[];
171  assert(aListOfInt is List<int>);
172
173  assert(aListOfInt.isEmpty);
174
175  aListOfInt.add(10);
176  aListOfInt.add(20);
177  assert(aListOfInt.length == 2);
178  assert(aListOfInt[0] == 10);
179  assert(aListOfInt[1] == 20);
180
181  final aSetOfInt = <int>{};
182  assert(aSetOfInt is Set<int>);
183
184  final aMapOfIntToDouble = <int, double>{};
185  assert(aMapOfIntToDouble is Map<int, double>);
186
187  // final aListOfBaseType = <BaseType>[SubType(), SubType()];
188}
189
190void testNuallable() {
191  int? a;
192  assert(a == null);
193  a = 3;
194  assert(a == 3);
195  int b = a!; // kotlin uses two !, while dart uses only one
196  assert(b == 3);
197
198  a = null;
199
200  b = a ?? 10; // if a is null ,then assign 10 to b, else assign a to b
201  assert(b == 10);
202
203  a = 20;
204  b = a ?? 10;
205  assert(b == 20);
206}
207
208void testTypeInference() {
209  var a = 1;
210  assert(a is int);
211
212  var b = 's';
213  assert(b is String);
214
215  var c = 3.7;
216  assert(c is double);
217
218  var d = ['1', '2', '3'];
219  assert(d is List<String>);
220
221  var f = {
222    'one': 1,
223    'two': 2,
224  };
225  assert(f is Map<String, int>);
226}
227
228void testDynamic() {
229  dynamic a = 1;
230  assert(a is int);
231
232  a = 2.5;
233  assert(a is double);
234
235  a = 'a';
236  assert(a is String);
237}
238
239void testObject() {
240  Object a = 1;
241  assert(a is int);
242  assert(a.runtimeType == int);
243
244  int i = a as int; // type casting
245  assert(i == 1);
246
247  a = 2.5;
248  assert(a is double);
249
250  a = 'a';
251  assert(a is String);
252}
253
254void testCompileTimeConstant() {
255  const a = 1;
256  assert(a is int);
257
258  // specify the type explicitly
259  const String b = 'hello';
260  assert(b == 'hello');
261}
262
263void testRuntimeConstant() {
264  double a = 5;
265  final b = a / 2;
266  assert(b is double);
267  assert(b == 2.5);
268
269  final int c = 3;
270  assert(c == 3);
271}
272
273void main() {
274  testDouble();
275  testInt();
276  testString();
277  testBoolean();
278  testList();
279  testList2();
280  testNuallable();
281  testTypeInference();
282  testDynamic();
283  testObject();
284  testCompileTimeConstant();
285  testRuntimeConstant();
286}
./code/test2.dart
 1// run it with
 2// dart --enable-asserts ./test2.dart
 3
 4int add(int a, int b) {
 5  return a + b;
 6}
 7
 8// if it contains a single return statement, it can be simplified
 9int add2(int a, int b) => a + b;
10
11// optional positional arguments.
12// we usually don't use positional arguments
13int func(int a, [int? b, int? c]) {
14  return a - (b ?? 0) + (c ?? 0);
15}
16
17int func2(int a, {int? b, int? c}) {
18  return a - (b ?? 0) + (c ?? 0);
19}
20
21int myMax(int a, int b) {
22  // like ?: in C/C++
23  return (a > b) ? a : b;
24}
25
26// both ways are fine to define a function type
27typedef int MyAdd(int a, int b); // argument names cannot be omitted
28
29// argument names can be omitted
30typedef MyAdd2 = int Function(int, int);
31// typedef MyAdd2 = int Function(int a, int b);
32
33void main() {
34  assert(add(2, 3) == 5);
35  assert(add2(2, 3) == 5);
36
37  // for positional arguments, we cannot ignore b if we want to pass c,
38  assert(func(10) == 10); //a i 10
39  assert(func(10, 3) == 7); // a is 10, b is 3, c is null
40  assert(func(10, null, 5) == 15); // a is 10, b is null, c is 5
41  assert(func(10, 3, 5) == 12); // a is 10, b is 3, c is 5
42
43  assert(func2(10) == 10);
44  assert(func2(10, c: 3) == 13);
45  assert(func2(10, b: 2) == 8);
46  assert(func2(10, c: 3, b: 2) == 11);
47  assert(func2(10, b: 2, c: 3) == 11);
48
49  MyAdd myAdd = add;
50  assert(myAdd(2, 3) == 5);
51
52  MyAdd2 myAdd2 = add;
53  assert(myAdd2(2, 3) == 5);
54
55  // define a function type
56
57  var f = (a, b) => a + b;
58  assert(f(2, 3) == 5);
59
60  assert(myMax(1, 2) == 2);
61}

control

./code/test-control.dart
  1// dart --enable-asserts ./test-control.dart
  2
  3void TestIf() {
  4  int a = 2;
  5  int b = 0;
  6  if (a > 1) {
  7    b = 3;
  8  } else {
  9    b = 4;
 10  }
 11
 12  assert(b == 3);
 13
 14  //like C/C++
 15  b = (a > 1) ? 10 : 20;
 16  assert(b == 10);
 17}
 18
 19void TestSwitchInt() {
 20  int a = 1;
 21  int b;
 22  switch (a) {
 23    case 10:
 24      b = 2;
 25      break;
 26    case 1:
 27      b = 3;
 28      break;
 29    default:
 30      b = 4;
 31      break;
 32  }
 33  assert(b == 3);
 34}
 35
 36void TestSwitchString() {
 37  String s = 'zero';
 38  int b;
 39  switch (s) {
 40    case 'zero':
 41      b = 0;
 42      break;
 43    case 'one':
 44      b = 1;
 45      break;
 46    default:
 47      b = -1;
 48      break;
 49  }
 50
 51  assert(b == 0);
 52}
 53
 54enum MyNumber {
 55  zero,
 56  one,
 57  two,
 58} // no trailing ;
 59
 60void TestSwitchEnum() {
 61  final n = MyNumber.one;
 62
 63  // counts from 0
 64  assert(n.index == 1);
 65
 66  int b = -1;
 67  switch (n) {
 68    case MyNumber.zero:
 69      b = 0;
 70      break;
 71    case MyNumber.one:
 72      b = 1;
 73      break;
 74    case MyNumber.two:
 75      b = 2;
 76      break;
 77    // no need to use default
 78  }
 79
 80  assert(b == 1);
 81}
 82
 83void TestWhile() {
 84  int i = 0;
 85  int sum = 0;
 86  while (i <= 3) {
 87    sum += i;
 88    i++;
 89  }
 90  assert(sum == 1 + 2 + 3);
 91}
 92
 93void TestDoWhile() {
 94  int i = 0;
 95  int sum = 0;
 96  do {
 97    sum += i;
 98    i++;
 99  } while (i <= 3);
100
101  assert(sum == 1 + 2 + 3);
102}
103
104void main() {
105  TestIf();
106  TestSwitchInt();
107  TestSwitchString();
108  TestSwitchEnum();
109  TestWhile();
110  TestDoWhile();
111}

record

./code/test_record.dart
 1// run it with
 2// dart --enable-asserts ./test_record.dart
 3
 4// records requires dart>=3.0
 5void test1() {
 6  (int, int) a;
 7
 8  // (2, 3) is immutable
 9  a = (2, 3);
10  assert(a.$1 == 2); // count from 1
11  assert(a.$2 == 3);
12
13  // for named fields in a record, we must use named assignment
14  ({int a, int b}) c = (a: 10, b: 20);
15  assert(c.a == 10);
16  assert(c.b == 20);
17
18  // mix of positional and named
19  (int, {int a, int b}) d;
20  d = (10, a: 20, b: 30);
21  assert(d.$1 == 10);
22  assert(d.a == 20);
23  assert(d.b == 30);
24
25  var f = (100, a: 200, b: 300, 400);
26  assert(f == (100, 400, a: 200, b: 300));
27
28  (int, int, {int a, int b}) h;
29
30  // named fields can appear any where
31  h = (a: 1, b: 2, 0, 3);
32
33  assert(h.$1 == 0);
34  assert(h.$2 == 3);
35  assert(h.a == 1);
36  assert(h.b == 2);
37
38  (num, Object) k = (42, 'a');
39  assert(k.$1 is int);
40  assert(k.$2 is String);
41
42  // as kotlin, to convert types
43  int k1 = k.$1 as int;
44  String k2 = k.$2 as String;
45
46  assert(k1 == k.$1);
47  assert(k2 == k.$2);
48}
49
50void main() {
51  test1();
52}

function

./code/test-function.dart
 1// dart --enable-asserts ./test-function.dart
 2int add(int a, int b) {
 3  return a + b;
 4}
 5
 6// b is optional.
 7// if b is not passed, it is null by default
 8// optional arguments must be placed at the end
 9int add2(int a, [int? b]) {
10  if (b == null) {
11    return a + 2;
12  }
13  return a + b;
14}
15
16// multiple optional arguments
17int add3(int a, [int? b, int? c]) {
18  return a + (b ?? 1) + (c ?? 2);
19}
20
21// optional argument with a default value
22int add4(int a, [int b = 10]) {
23  return a + b;
24}
25
26// b must be passed by name
27int add5(int a, {required int b}) {
28  return a + b;
29}
30
31// b is an optional name parameter
32int add6(int a, {int? b}) {
33  return a + (b ?? 3);
34}
35
36void main() {
37  int c = add(2, 3);
38  assert(c == 5);
39
40  c = add2(10);
41  assert(c == 12);
42
43  c = add2(10, 5);
44  assert(c == 15);
45
46  c = add3(10);
47  assert(c == 13);
48
49  c = add3(10, 2);
50  assert(c == 14);
51
52  c = add4(2);
53  assert(c == 12);
54
55  c = add5(2, b: 3);
56  assert(c == 5);
57
58  c = add6(5);
59  assert(c == 8);
60
61  c = add6(6);
62  assert(c == 9);
63}

class

./code/test-class.dart
  1// dart run --enable-asserts ./test-class.dart
  2
  3class User {
  4  int id = 0;
  5  String name = '';
  6
  7  @override
  8  String toString() {
  9    return 'User(id: $id, name: $name)';
 10  }
 11
 12  String toJson() {
 13    return '{"id":$id, "name":"$name"}';
 14  }
 15} // no trailing ;
 16
 17void testUser() {
 18  final user = User();
 19  print(user); // User(id: 0, name: )
 20
 21  user.id = 20;
 22  print(user); // User(id: 20, name: )
 23  print(user.toJson()); // {"id":20, "name":""}
 24
 25  var user2 = User();
 26  user2.name = 'hello';
 27  user2.id = 10;
 28  print(user2); // User(id: 10, name: hello)
 29
 30  // cascade notation
 31  user2 = User()
 32    ..name = 'hello'
 33    ..id = 10;
 34  print(user2); // User(id: 10, name: hello)
 35
 36  // assign by reference
 37  var user3 = user2;
 38  user3.id = 100;
 39  assert(user2.id == 100);
 40}
 41
 42class Point {
 43  int _x = 0;
 44
 45  // getter
 46  int get x => _x;
 47
 48  // getter
 49  int get x2 => _x + 2;
 50
 51  // computed property
 52  int get x3 {
 53    return _x + 3;
 54  }
 55
 56  // setter
 57  set myX(int v) => _x = v;
 58
 59  // define another getter
 60  int get myX => _x;
 61
 62  // validate the value
 63  set myX2(int v) {
 64    if (v < 10) {
 65      print('v should be >= 10. Given: $v');
 66      return;
 67    }
 68
 69    _x = v;
 70  }
 71}
 72
 73void testPoint() {
 74  final p = Point();
 75  assert(p._x == 0);
 76  assert(p.x == 0);
 77  assert(p.x2 == 2);
 78
 79  p._x = 100;
 80  assert(p.x == 100);
 81  assert(p.x2 == 102);
 82  assert(p.x3 == 103);
 83
 84  p.myX = 5;
 85  assert(p._x == 5);
 86  assert(p.x == 5);
 87  assert(p.myX == 5);
 88
 89  p.myX2 = 12;
 90  assert(p.x == 12);
 91
 92  p.myX2 = 9; // we have required the value should be >= 10
 93  assert(p.x == 12);
 94
 95  p.myX2 = 13;
 96  assert(p.x == 13);
 97}
 98
 99class Point2 {
100  // long form constructor
101  // x and y are required positional arguments
102  Point2(int x, int y) {
103    this.x = x;
104    this.y = y;
105  }
106  int x = 0;
107  int y = 0;
108}
109
110void testPoint2() {
111  final p = Point2(10, 20);
112  assert(p.x == 10);
113  assert(p.y == 20);
114}
115
116class Point3 {
117  // short form constructor
118  Point3(this.x, this.y);
119  int x = 0;
120  int y = 0;
121}
122
123void testPoint3() {
124  final p = Point3(100, 200);
125  assert(p.x == 100);
126  assert(p.y == 200);
127}
128
129// we can have many named constructors
130class Point4 {
131  Point4(this.x, this.y);
132
133  // named constructor
134  Point4.myPoint() {
135    x = 10;
136    y = 20;
137  }
138
139  Point4.myPoint2(int x) {
140    this.x = x;
141    y = 200;
142  }
143
144  // forwarding constructor, this(1, 2) is Point4(1, 2)
145  Point4.myPoint3() : this(1, 2);
146
147  factory Point4.myPoint4(int x, int y) {
148    // there is no this inside the factory constructor
149    // we need to create and return an object
150
151    // we can validate, and even change the passed argument
152    return Point4(x + 2, y + 3);
153  }
154
155  int x = 0;
156  int y = 0;
157}
158
159void testPoint4() {
160  var p = Point4.myPoint();
161  assert(p.x == 10);
162  assert(p.y == 20);
163
164  p = Point4.myPoint2(-1);
165  assert(p.x == -1);
166  assert(p.y == 200);
167
168  p = Point4.myPoint3();
169  assert(p.x == 1);
170  assert(p.y == 2);
171
172  p = Point4.myPoint4(11, 22);
173  assert(p.x == 11 + 2);
174  assert(p.y == 22 + 3);
175}
176
177void main() {
178  testUser();
179  testPoint();
180  testPoint2();
181  testPoint3();
182  testPoint4();
183}

null

./code/test-null.dart
 1// dart run --enable-asserts ./test-null.dart
 2
 3class User {
 4  int id = 1;
 5}
 6
 7void test1() {
 8  int? a; // default to null
 9
10  assert(a == null);
11
12  a ??= 3;
13  assert(a == 3);
14
15  a ??= 5; // a is not null, so it is a no-op
16  assert(a == 3);
17
18  a = null;
19
20  int b = a ?? 10; // a is null, so 10 is assigned to b
21  assert(b == 10);
22
23  a = 1;
24  b = a ?? 5; // a is not null, so a is assigned to b
25  assert(b == 1);
26
27  a = null;
28  // b = a; // compile time error since a is null
29
30  // b = a!; // runtime exception: Null check operator used on a null value
31
32  User? u;
33  int id = u?.id ?? 10;
34  assert(id == 10);
35
36  u = User();
37  id = u?.id ?? 10;
38  assert(id == 1);
39}
40
41void main() {
42  test1();
43}

list

./code/test-list.dart
 1// dart run --enable-asserts ./test-list.dart
 2
 3void test1() {
 4  var a = [1, 2, 3]; // infer types automatically
 5
 6  List<int> b = [1, 2, 3]; // Use List<int> explicitly
 7  print(b);
 8
 9  var c = <int>[]; // an empty list with a specified type
10  assert(c.isEmpty == true);
11  c.add(1);
12
13  assert(c.isEmpty == false);
14
15  c.add(3);
16  c.add(2);
17  assert(c.length == b.length); // get number of elements
18  print(c); // [1, 3, 2]
19  c.sort(); // sort in-place
20  print(c); // [1, 2, 3]
21}
22
23// use a for loop like c/c++
24void test2() {
25  var a = [1, 2, 3];
26  var sum = 0;
27  for (int i = 0; i < a.length; i++) {
28    sum += a[i];
29  }
30  assert(sum == 6);
31}
32
33void test3() {
34  var a = [1, 2, 3];
35  var sum = 0;
36  for (final i in a) {
37    sum += i;
38  }
39  assert(sum == 6);
40}
41
42// the spread operator
43void test4() {
44  var a = [1, 2];
45  var b = [3];
46  var c = [...a, ...b];
47  print(c); // 1, 2, 3
48
49  c = [10, ...b, ...a];
50  print(c); // 10, 3, 1, 2
51}
52
53// collection for
54void test5() {
55  var a = [1, 2, 3];
56
57  // add all elements from a
58  var b = [10, for (final i in a) i];
59  print(b); // [10, 1, 2, 3]
60
61  // add elements from a whose value > 1
62  b = [
63    10,
64    for (final i in a)
65      if (i > 1) i
66  ];
67  print(b); // [10, 2, 3]
68
69  // convert a list of integers to a list of strings
70  var s = [for (final i in a) i.toString()];
71  print(s); // [1, 2, 3]
72}
73
74void main() {
75  test1();
76  test2();
77  test3();
78  test4();
79  test5();
80}

set

./code/test-set.dart
 1// dart run --enable-asserts ./test-set.dart
 2
 3// two ways to define an empty set
 4void test1() {
 5  final Set<int> a = {};
 6  assert(a.isEmpty == true);
 7
 8  final b = <int>{};
 9  assert(b.isEmpty == true);
10}
11
12void test2() {
13  var a = {1, 2, 1};
14  assert(a.length == 2);
15
16  assert(a.contains(1)); // 1 is inside the set
17  assert(a.contains(10) == false); // 10 is not inside the set
18
19  a.add(10);
20  assert(a.contains(10)); // now 10 is inside the set
21  assert(a.length == 3);
22
23  a.remove(2);
24  assert(a.length == 2);
25  assert(a.contains(2) == false); // now 2 is not inside the set
26
27  var b = [5, 1];
28  a.addAll(b);
29  print(a); // {1, 10, 5}
30
31  // iterating a set
32  var sum = 0;
33  for (final i in a) {
34    sum += i;
35  }
36  assert(sum == 1 + 10 + 5);
37}
38
39// convert a list to a set
40// convert a set to a list
41void test3() {
42  var a = [1, 2, 1];
43  var b = a.toSet();
44  print(b); // {1, 2}
45  a = b.toList(); // [1, 2]
46  print(a);
47}
48
49void test4() {
50  var a = <int>{1, 2};
51  var b = a; // reference assigment
52  b.add(3);
53  assert(a.contains(3));
54
55  b = a.toSet(); // real copy
56  b.add(4);
57  assert(a.contains(4) == false);
58}
59
60void main() {
61  test1();
62  test2();
63  test3();
64  test4();
65}

map

./code/test-map.dart
 1// dart run --enable-asserts ./test-map.dart
 2
 3// two ways to create an empty map
 4void test1() {
 5  final Map<String, int> a = {};
 6  final b = <String, int>{};
 7  assert(a.isEmpty);
 8  assert(b.isEmpty);
 9}
10
11// create a map from literals
12void test2() {
13  final a = {
14    'apple': 20,
15    'cat': 10,
16  };
17
18  assert(a['cat'] == 10);
19  assert(a['dog'] == null); // return null if the key does not exist
20
21  a['dog'] = 50;
22  assert(a['dog'] == 50);
23
24  a['dog'] = 1;
25  assert(a['dog'] == 1);
26
27  a.remove('dog'); // remove an element from a map
28  assert(a['dog'] == null);
29
30  print(a); // {apple: 20, cat: 10}
31  assert(a.length == 2);
32  assert(a.isEmpty == false);
33  assert(a.isNotEmpty == true);
34
35  assert(a.containsKey('dog') == false);
36}
37
38void test3() {
39  var a = <String, int>{
40    'one': 1,
41    'two': 2,
42  };
43
44  var sum = 0;
45
46  // iterate the keys
47  //
48  // a[k] is of type int?
49  for (final k in a.keys) {
50    sum += a[k]!;
51  }
52  assert(sum == 3);
53
54  sum = 0;
55
56  // iterate the values
57  for (final v in a.values) {
58    sum += v;
59  }
60  assert(sum == 3);
61
62  sum = 0;
63
64  // iterate with key and value
65  for (final entry in a.entries) {
66    sum += entry.key.length + entry.value;
67  }
68  assert(sum == 3 + 3 + 1 + 2);
69}
70
71void main() {
72  test1();
73  test2();
74  test3();
75}

string

./code/test-string.dart
  1// dart run --enable-asserts ./test-string.dart
  2
  3// there is no char type
  4// both '' and "" are ok
  5void test1() {
  6  var s = 'hello';
  7  s = "hello";
  8}
  9
 10void test2() {
 11  var s = 'hello';
 12  var s2 = s.toUpperCase();
 13  assert(s2 == 'HELLO');
 14
 15  var s3 = s2.toLowerCase();
 16  assert(s3 == 'hello');
 17
 18  // trim
 19  s = ' hello ';
 20  s2 = s.trim();
 21  assert(s2 == 'hello');
 22
 23  // trim can also trim \n \r \t
 24  s = ' hello\n\r\t';
 25  s2 = s.trim();
 26  assert(s2 == 'hello');
 27
 28  s = ' hello\n\r\t';
 29  s2 = s.trimLeft();
 30  assert(s2 == 'hello\n\r\t');
 31
 32  s = ' hello\n\r\t';
 33  s2 = s.trimRight();
 34  assert(s2 == ' hello');
 35}
 36
 37void test3() {
 38  var s = '1'.padLeft(2, '0');
 39  assert(s == '01');
 40
 41  // 11 is already of length 2, so the pad is a no-op
 42  s = '11'.padLeft(2, '0');
 43  assert(s == '11');
 44}
 45
 46// several ways to convert an integer to a string
 47void test4() {
 48  var s = 11.toString();
 49  assert(s == '11');
 50
 51  // string interpolation
 52  var i = 11;
 53  s = '$i';
 54  assert(s == '11');
 55}
 56
 57// split a string
 58// join a list of string
 59void test5() {
 60  var s = '1,2,3,4';
 61  var a = s.split(',');
 62  assert(a is List<String>);
 63
 64  s = a.join('-');
 65  assert(s == '1-2-3-4');
 66}
 67
 68void test6() {
 69  var a = '1,2,3';
 70  var b = a.replaceAll(',', '-');
 71  assert(b == '1-2-3');
 72
 73  a = '1,2,3';
 74  b = a.replaceFirst(',', '-');
 75  assert(b == '1-2,3');
 76}
 77
 78// use a string buffer to build a string
 79void test7() {
 80  var s = '0,1,2,3';
 81  final buffer = StringBuffer();
 82  var sep = '';
 83  for (int i = 0; i < 4; i++) {
 84    buffer.write(sep);
 85    buffer.write('$i');
 86    sep = ',';
 87  }
 88  var s2 = buffer.toString();
 89  assert(s == s2);
 90}
 91
 92void test8() {
 93  var s = 'hello';
 94  assert(s.startsWith('h') == true);
 95  assert(s.startsWith('hel') == true);
 96  assert(s.startsWith('hi') == false);
 97
 98  assert(s.endsWith('o') == true);
 99  assert(s.endsWith('lo') == true);
100  assert(s.endsWith('alo') == false);
101
102  assert(s.contains('ll'));
103  assert(s.contains('lol') == false);
104}
105
106void main() {
107  test1();
108  test2();
109  test3();
110  test4();
111  test5();
112  test6();
113  test7();
114  test8();
115}

events

./code/test-events.dart
 1// dart run --enable-asserts ./test-events.dart
 2
 3/*
 4There are two queues:
 5 - event queue (low priority)
 6 - micro task queue (high priority)
 7
 8*/
 9
10/*
11it prints
12first
13third
14second
15*/
16void test1() {
17  print('first');
18
19  // add task to the event queue
20  Future(() => print('second'));
21  print('third');
22}
23
24/*
25it prints
26first
27fourth
28third
29second
30*/
31void test2() {
32  print('first');
33
34  // add task to the event queue
35  Future(() => print('second'));
36
37  // add task to the micro task queue
38  Future.microtask(() => print('third'));
39  print('fourth');
40}
41
42void main() {
43  // test1();
44  test2();
45}

isolate

./code/test-isolate.dart
 1// dart run --enable-asserts ./test-isolate.dart
 2
 3import 'dart:isolate';
 4
 5void test1Isolate(SendPort sendPort) {
 6  sendPort.send('hello');
 7  sendPort.send('world');
 8  sendPort.send(null);
 9}
10
11Future<void> test1() async {
12  final receivePort = ReceivePort();
13  final isolate = await Isolate.spawn<SendPort>(
14    test1Isolate,
15    receivePort.sendPort,
16  );
17
18  receivePort.listen((Object? message) {
19    if (message is String) {
20      print('message: $message');
21    } else if (message == null) {
22      receivePort.close();
23      isolate.kill();
24    }
25  });
26}
27
28void main() {
29  test1();
30}