This repository has been archived by the owner on Aug 4, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 29
/
ch02.xml
3029 lines (2287 loc) · 97.8 KB
/
ch02.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
<chapter>
<title>A Tour of the Dart Language</title>
<para>This chapter shows you how to use each major Dart feature, from
variables and operators to classes and libraries, with the assumption that
you already know how to program in another language.</para>
<note>
<para>To play with each feature, create a server application project in
Dart Editor, as described in <xref linkend="ch01-editor" />.</para>
</note>
<para>Consult the <ulink url="http://www.dartlang.org/docs/spec/">Dart
Language Specification</ulink> whenever you want more details about a
language feature.</para>
<sect1 id="main-print">
<title>A basic Dart program</title>
<para>The following code uses many of Dart’s most basic features.</para>
<programlisting>(MERGE(basic_dart_program))</programlisting>
<para>Here’s what this program uses that applies to all (or almost all)
Dart apps:</para>
<variablelist>
<varlistentry>
<term><literal>// <replaceable>This is a
comment.</replaceable></literal></term>
<listitem>
<para>Use // to indicate that the rest of the line is a comment.
Alternatively, use /* ... */. For details, see <xref
linkend="comments" />.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><literal>num</literal></term>
<listitem>
<para>A type. Some of the other built-in types are String, int, and
bool.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><literal>100</literal></term>
<listitem>
<para>A number <glossterm>literal</glossterm>. Literals are a kind
of compile-time constant.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><literal>print()</literal></term>
<listitem>
<para>A handy way to display output.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><literal>'...'</literal> (or <literal>"..."</literal>)</term>
<listitem>
<para>A string literal.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><literal>$<replaceable>variableName</replaceable></literal> (or
<literal>${<replaceable>expression</replaceable></literal><literal>}</literal>)</term>
<listitem>
<para>String interpolation: including a variable or expression’s
string equivalent inside of a string literal. For more information,
see <xref linkend="strings" />.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><literal>main()</literal></term>
<listitem>
<para>The special, <emphasis>required</emphasis>, top-level function
where app execution starts.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><literal>var</literal></term>
<listitem>
<para>A way to declare a variable without specifying its
type.</para>
</listitem>
</varlistentry>
</variablelist>
<note>
<para>Our code follows the conventions in the <ulink
url="http://www.dartlang.org/articles/style-guide/">Dart Style
Guide.</ulink> For example, we use two-space indentation.</para>
</note>
</sect1>
<sect1 id="ch02-concepts">
<title>Important concepts</title>
<para>As you learn about the Dart language, keep these facts and concepts
in mind:</para>
<itemizedlist>
<listitem>
<para>Everything you can place in a variable is an
<emphasis>object</emphasis>, and every object is an instance of a
<emphasis>class</emphasis>. Even numbers and functions are objects.
All objects inherit from the <ulink
url="http://api.dartlang.org/dart_core/Object.html">Object</ulink>
class.</para>
</listitem>
<listitem>
<para>Specifying static types (such as <literal>num</literal> in the
preceding example) clarifies your intent and enables static checking
by tools, but it’s optional. (You might notice when you’re debugging
your code that objects with no specified type get a special type:
<literal>dynamic</literal>.)</para>
</listitem>
<listitem>
<para>Dart parses all your code before running it. You can provide
tips to Dart—for example, by using types or compile-time constants—to
catch errors or help your code run faster.</para>
</listitem>
<listitem>
<para>Dart supports top-level functions (such as main()), as well as
functions tied to a class or object (<emphasis>static</emphasis> and
<emphasis>instance methods</emphasis>, respectively).</para>
</listitem>
<listitem>
<para>Similarly, Dart supports top-level
<emphasis>variables</emphasis>, as well as variables tied to a class
or object (static and instance variables). Instance variables are
sometimes known as <glossterm>fields</glossterm> or
<glossterm>properties</glossterm>.</para>
</listitem>
<listitem>
<para>Unlike Java, Dart doesn’t have the keywords
<literal>public</literal>, <literal>protected</literal>, and
<literal>private</literal>. If an identifier starts with an underscore
(_), it’s private to its library. For details, see <xref
linkend="libraries" />.</para>
</listitem>
<listitem>
<para><glossterm>Identifiers</glossterm> can start with a letter or _,
followed by any combination of those characters plus digits.</para>
</listitem>
<listitem>
<para>Sometimes it matters whether something is an
<emphasis>expression</emphasis> or a <emphasis>statement</emphasis>,
so we’ll be precise about those two words.</para>
</listitem>
<listitem>
<para>Dart tools can report two kinds of errors: warnings and errors.
Warnings are just hints that your code might not work, but they don’t
prevent your program from executing. Errors can be either compile-time
or run-time. A compile-time error prevents the code from executing at
all; a run-time error results in an exception <xref
linkend="exceptions" xrefstyle="select:page" /> being raised while the
code executes.</para>
</listitem>
<listitem>
<para>Dart has two <glossterm>runtime modes</glossterm>: production
and checked. Production is faster, but checked is helpful at
development.</para>
</listitem>
</itemizedlist>
<sect2 id="ch02-runtime-modes">
<title>Runtime modes</title>
<para>We recommend that you develop and debug in checked mode, and
deploy to production mode.</para>
<para><emphasis>Production mode</emphasis> is the default runtime mode
of a Dart program, optimized for speed. Production mode ignores assert
statements <xref linkend="assert" xrefstyle="select:page" /> and static
types.</para>
<para><emphasis>Checked mode</emphasis> is a developer-friendly mode
that helps you catch some type errors during runtime. For example, if
you assign a non-number to a variable declared as a
<literal>num</literal>, then checked mode throws an exception.</para>
</sect2>
</sect1>
<sect1 id="variables">
<title>Variables</title>
<para>Here’s an example of creating a variable and assigning a value to
it:</para>
<programlisting>(MERGE(creating_a_variable))</programlisting>
<para>Variables are references. The variable called
<literal>name</literal> contains a reference to a String object with a
value of <quote>Bob</quote>.</para>
<sect2 id="variables-default-value">
<title>Default value</title>
<para>Uninitialized variables have an initial value of
<literal>null</literal>. Even variables with numeric types are initially
null, because numbers are objects.</para>
<programlisting>(MERGE(numbers_are_objects))</programlisting>
<note>
<para>The assert() call is ignored in production mode. In checked
mode, <literal>assert(<replaceable>condition</replaceable>)</literal>
throws an exception unless <replaceable>condition</replaceable> is
true. For details, see <xref linkend="assert" />.</para>
</note>
</sect2>
<sect2 id="variables-optional-types">
<title>Optional types</title>
<para>You have the option of adding static types to your variable
declarations:</para>
<programlisting>(MERGE(static_types))</programlisting>
<para>Adding types is a way to clearly express your intent. Tools such
as compilers and editors can use these types to help you, by providing
early warnings for bugs and code completion.</para>
<note>
<para>This chapter follows the <ulink
url="http://www.dartlang.org/articles/style-guide/#type-annotations">style
guide recommendation</ulink> of using <literal>var</literal>, rather
than type annotations, for local variables.</para>
</note>
</sect2>
<sect2>
<title>Final and const</title>
<para>If you never intend to change a variable, use
<literal>final</literal> or <literal>const</literal>, either instead of
<literal>var</literal> or in addition to a type. A final variable can be
set only once; a const variable is a compile-time constant.</para>
<para>A local, top-level, or class variable that’s declared as
<literal>final</literal> is initialized the first time it’s used.</para>
<programlisting>(MERGE(final_initialization))</programlisting>
<note>
<para>Lazy initialization of final variables helps apps start up
faster.</para>
</note>
<para>Use <literal>const</literal> for variables that you want to be
compile-time constants. Where you declare the variable, set the value to
a compile-time constant such as a literal, a const variable, or the
result of an arithmetic operation on constant numbers.</para>
<programlisting>(MERGE(const))</programlisting>
</sect2>
</sect1>
<sect1 id="built-in-types">
<title>Built-in types</title>
<para>The Dart language has special support for the following
types:</para>
<itemizedlist>
<listitem>
<simpara>numbers</simpara>
</listitem>
<listitem>
<simpara>strings</simpara>
</listitem>
<listitem>
<simpara>booleans</simpara>
</listitem>
<listitem>
<simpara>lists (also known as <emphasis>arrays</emphasis>)</simpara>
</listitem>
<listitem>
<simpara>maps</simpara>
</listitem>
</itemizedlist>
<para>You can initialize an object of any of these special types using a
literal. For example, <literal>'this is a string'</literal> is a string
literal, and <literal>true</literal> is a boolean literal.</para>
<para>Because every variable in Dart refers to an object—an instance of a
<emphasis>class</emphasis>—you can usually use
<emphasis>constructors</emphasis> to initialize variables. Some of the
built-in types have their own constructors. For example, you can use the
Map() constructor to create a map, using code such as <literal>new
Map()</literal>.</para>
<sect2 id="numbers">
<title>Numbers</title>
<para>Dart numbers come in two flavors:</para>
<variablelist>
<varlistentry>
<term><ulink
url="http://api.dartlang.org/dart_core/int.html"><literal>int</literal></ulink></term>
<listitem>
<para>Integers of arbitrary size</para>
</listitem>
</varlistentry>
<varlistentry>
<term><ulink
url="http://api.dartlang.org/dart_core/double.html"><literal>double</literal></ulink></term>
<listitem>
<para>64-bit (double-precision) floating-point numbers, as
specified by the IEEE 754 standard</para>
</listitem>
</varlistentry>
</variablelist>
<para>Both <literal>int</literal> and <literal>double</literal> are
subtypes of <ulink
url="http://api.dartlang.org/dart_core/num.html"><literal>num</literal>.</ulink>
The num type includes basic operators such as +, -, /, and *, as well as
bitwise operators such as >>. The num type is also where you’ll
find abs(), ceil(), and floor(), among other methods. If num and its
subtypes don’t have what you’re looking for, the <ulink
url="http://api.dartlang.org/dart_core/Math.html">Math</ulink> class
might.</para>
<para>Integers are numbers without a decimal point. Here are some
examples of defining integer literals:</para>
<programlisting>(MERGE(integer_literals))</programlisting>
<note>
<para>In JavaScript produced from Dart code, big integers currently
behave differently than they do when the same Dart code runs in the
Dart VM. For details, see <ulink
url="http://dartbug.com/1533"></ulink>.</para>
</note>
<para>If a number includes a decimal, it is a double. Here are some
examples of defining double literals:</para>
<programlisting>(MERGE(double_literals))</programlisting>
<para>Here’s how you turn a string into a number, or vice versa:</para>
<programlisting>(MERGE(number_conversion))</programlisting>
<para>The num type specifies the traditional bitwise shift (<<,
>>), AND (&), and OR (|) operators. For example:</para>
<programlisting>(MERGE(bit_shifting))</programlisting>
</sect2>
<sect2 id="strings">
<title>Strings</title>
<para>A Dart string is a sequence of UTF-16 code units. You can use
either single or double quotes to create a string:</para>
<programlisting>(MERGE(quoting))</programlisting>
<para>You can put the value of an expression inside a string by using
${<emphasis>expression</emphasis>}. If the expression is an identifier,
you can skip the {}. To get the string corresponding to an object, Dart
calls the object’s toString() method.</para>
<programlisting>(MERGE(string_interpolation))</programlisting>
<note>
<para>The <literal>==</literal> operator tests whether two objects are
equivalent. Two strings are equivalent if they have the same
characters.</para>
</note>
<para>You can concatenate strings using adjacent string literals:</para>
<programlisting>(MERGE(adjacent_string_literals))</programlisting>
<para>Another way to create a multi-line string: use a triple quote with
either single or double quotation marks.</para>
<programlisting>(MERGE(triple_quotes))</programlisting>
<para>You can create a <quote>raw</quote> string by prefixing it with
<literal>r</literal>.</para>
<programlisting>(MERGE(raw_strings))</programlisting>
<para>For more information on using strings, see <xref
linkend="ch03-strings-and-regular-expressions" />.</para>
</sect2>
<sect2 id="booleans">
<title>Booleans</title>
<para>To represent boolean values, Dart has a type named
<literal>bool</literal>. Only two objects have type bool: the boolean
literals, <literal>true</literal> and <literal>false</literal>.</para>
<para>When Dart expects a boolean value, only the value
<literal>true</literal> is treated as true. All other values are treated
as false. Unlike in JavaScript, values such as <literal>1</literal>,
<literal>"aString"</literal>, and <literal>someObject</literal> are all
treated as false.</para>
<para>For example, consider the following code, which is valid both as
JavaScript and as Dart code:</para>
<programlisting>(MERGE(strictly_booleans))</programlisting>
<para>If you run this code as JavaScript, without compiling to Dart, it
prints <quote>You have a name!</quote> because <literal>name</literal>
is a non-null object. However, in Dart running in <emphasis>production
mode</emphasis>, the above doesn’t print at all because
<literal>name</literal> is converted to <literal>false</literal>
(because <literal>name != true</literal>). In Dart running in
<emphasis>checked mode</emphasis>, the above code throws an exception
because the <literal>name</literal> variable is not a bool.</para>
<para>Here’s another example of code that behaves differently in
JavaScript and Dart:</para>
<programlisting>(MERGE(if_one))</programlisting>
<note>
<para>The previous two samples work only in production mode, not
checked mode. In checked mode, an exception is thrown if a non-boolean
is used when a boolean value is expected.</para>
</note>
<para>Dart’s treatment of booleans is designed to avoid the strange
behaviors that can arise when many values can be treated as true. What
this means for you is that, instead of using code like
<literal>if (<replaceable>nonbooleanValue</replaceable>)</literal>,
you should instead explicitly check for values. For example:</para>
<programlisting>(MERGE(empty_string))</programlisting>
</sect2>
<sect2 id="lists">
<title>Lists</title>
<para>Perhaps the most common collection in nearly every programming
language is the <emphasis>array</emphasis>, or ordered group of objects.
In Dart, arrays are <ulink
url="http://api.dartlang.org/dart_core/List.html">List</ulink> objects,
so we usually just call them <emphasis>lists</emphasis>.</para>
<para>Dart list literals look like JavaScript array literals. Here’s a
simple Dart list:</para>
<programlisting>(MERGE(list_literal))</programlisting>
<para>Lists use zero-based indexing, where 0 is the index of the first
element and <literal>list.length - 1</literal> is the index of the last
element. You can get a list’s length and refer to list elements just as
you would in JavaScript:</para>
<programlisting>(MERGE(list_indexing))</programlisting>
<para>The List type and its supertype, <ulink
url="http://api.dartlang.org/dart_core/Collection.html">Collection</ulink>,
have many handy methods for manipulating lists. For more information
about lists, see <xref linkend="generics" /> and <xref
linkend="ch03-collections" />.</para>
</sect2>
<sect2 id="maps">
<title>Maps</title>
<para>In general, a map is an object that associates keys and values.
Dart support for maps is provided by map literals and the <ulink
url="http://api.dartlang.org/dart_core/Map.html">Map</ulink>
type.</para>
<para>Here’s a simple Dart map:</para>
<programlisting>(MERGE(map_literal))</programlisting>
<para>In map literals, each <emphasis>key</emphasis> must be a string.
If you use a Map constructor, any object can be a key.</para>
<programlisting>(MERGE(map_constructor))</programlisting>
<para>A map <emphasis>value</emphasis> can be any object, including
null.</para>
<para>You add a new key-value pair to an existing map just as you would
in JavaScript:</para>
<programlisting>(MERGE(map_add_item))</programlisting>
<para>You retrieve a value from a map the same way you would in
JavaScript:</para>
<programlisting>(MERGE(map_retrieve_item))</programlisting>
<para>If you look for a key that isn’t in a map, you get a null in
return.</para>
<programlisting>(MERGE(map_missing_key))</programlisting>
<para>Use <literal>.length</literal> to get the number of key-value
pairs in the map:</para>
<programlisting>(MERGE(map_length))</programlisting>
<para>For more information about maps, see <xref linkend="generics" />
and <xref linkend="ch03-maps-aka-dictionaries-or-hashes" />.</para>
</sect2>
</sect1>
<sect1 id="functions">
<title>Functions</title>
<para>Here’s an example of implementing a function:</para>
<programlisting>(MERGE(function_example))</programlisting>
<para>Although the style guide recommends specifying the parameter and
return types, you don’t have to:</para>
<programlisting>(MERGE(function_omitting_types))</programlisting>
<para>For functions that contain just one expression, you can use a
shorthand syntax:</para>
<programlisting>(MERGE(function_shorthand))</programlisting>
<para>The <literal>=> <replaceable>expr</replaceable>;</literal> syntax
is a shorthand for <literal>{ return
<replaceable>expr</replaceable>;}</literal>. In the printNumber() function
above, the expression is the call to the top-level print()
function.</para>
<note>
<para>Only an <emphasis>expression</emphasis>—not a
<emphasis>statement</emphasis>—can appear between the arrow (=>) and
the semicolon (;). For example, you can’t put an if statement <xref
linkend="if-else" xrefstyle="select: page" /> there, but you can use a
conditional (?:) expression <xref linkend="op-other"
xrefstyle="select: page" />.</para>
</note>
<para>You can use types with =>, although the convention is not to do
so.</para>
<programlisting>(MERGE(function_types))</programlisting>
<para>Here’s an example of calling a function:</para>
<programlisting>(MERGE(function_calling))</programlisting>
<para>A function can have two types of parameters: required and optional.
The required parameters are listed first, followed by any optional
parameters.</para>
<sect2 id="functions-optional-parameters">
<title>Optional parameters</title>
<para>Optional parameters can be either positional or named, but not
both.</para>
<para>Both kinds of optional parameter can have default values. The
default values must be compile-time constants such as literals. If no
default value is provided, the value is <literal>null</literal>.</para>
<para>If you need to know whether the caller passed in a value for an
optional parameter, use the syntax
<literal>?<replaceable>param</replaceable></literal>.</para>
<programlisting>(MERGE(checking_optional_parameter_value_existence))</programlisting>
<sect3 id="functions-optional-named-parameters">
<title>Optional named parameters</title>
<para>When calling a function, you can specify named parameters using
<literal><replaceable>paramName</replaceable>:
<replaceable>value</replaceable></literal>. For example:</para>
<programlisting>(MERGE(use_named_parameters))</programlisting>
<para>When defining a function, use
<literal>{<replaceable>param1</replaceable>,
<replaceable>param2</replaceable>, …}</literal> to specify named
parameters.</para>
<programlisting>(MERGE(specify_named_parameters))</programlisting>
<para>Use a colon (<literal>:</literal>) to specify default
values.</para>
<programlisting>(MERGE(specify_default_values))</programlisting>
<note>
<para>The preceding two examples use documentation comments <xref
linkend="comments-doc" xrefstyle="select:page" />.</para>
</note>
</sect3>
<sect3 id="functions-optional-positional-parameters">
<title>Optional positional parameters</title>
<para>Wrapping a set of function parameters in <literal>[]</literal>
marks them as optional positional parameters.</para>
<programlisting>String say(String from, String msg, [String device]) {
var result = '$from says $msg';
if (device != null) {
result = '$result with a $device';
}
return result;
}</programlisting>
<para>Here’s an example of calling this function without the optional
parameter:</para>
<programlisting>assert(say('Bob', 'Howdy') == 'Bob says Howdy');</programlisting>
<para>And here’s an example of calling this function with the third
parameter:</para>
<programlisting>assert(say('Bob', 'Howdy', 'smoke signal') ==
'Bob says Howdy with a smoke signal');</programlisting>
<para>Use <literal>=</literal> to specify default values.</para>
<programlisting>String say(String from, String msg,
[String device='carrier pigeon', String mood]) {
var result = '$from says $msg';
if (device != null) {
result = '$result with a $device';
}
if (mood != null) {
result = '$result (in a $mood mood)';
}
return result;
}
assert(say('Bob', 'Howdy') == 'Bob says Howdy with a carrier pigeon'); </programlisting>
</sect3>
</sect2>
<sect2>
<title>Functions as first-class objects</title>
<para>You can pass a function as a parameter to another function. For
example:</para>
<programlisting>printElement(element) {
print(element);
}
var list = [1,2,3];
list.forEach(printElement); // Pass printElement as a parameter.</programlisting>
<para>You can also assign a function to a variable, such as:</para>
<programlisting>var loudify = (msg) => '!!! ${msg.toUpperCase()} !!!';
assert(loudify('hello') == '!!! HELLO !!!');</programlisting>
</sect2>
<sect2>
<title>Lexical closures</title>
<para>Functions can close over variables defined in surrounding scopes.
In the following example, makeAdder() captures the variable
<literal>n</literal> and makes it available to the function that
makeAdder() returns. Wherever the returned function goes, it remembers
<literal>n</literal>.</para>
<programlisting>/// Returns a function that adds [n] to the function's argument.
Function makeAdder(num n) {
return (num i) => n + i;
}
main() {
var add2 = makeAdder(2); // Create a function that adds 2.
var add4 = makeAdder(4); // Create a function that adds 4.
assert(add2(3) == 5);
assert(add4(3) == 7);
}</programlisting>
</sect2>
<sect2>
<title>Return values</title>
<para>All functions return a value. If no return value is specified, the
statement <literal>return null;</literal> is implicitly appended to the
function body.</para>
</sect2>
</sect1>
<sect1 id="operators">
<title>Operators</title>
<para>Dart defines the operators shown in <xref
linkend="operator_table" />. You can override many of these operators, as
described in <xref linkend="classes-operators" />.</para>
<table class="operatorTable" id="operator_table">
<title>Operators and their precedence</title>
<tgroup cols="2">
<thead>
<row>
<entry>Description</entry>
<entry>Operator</entry>
</row>
</thead>
<tbody>
<row>
<entry>unary postfix and argument definition test</entry>
<entry class="operatorList"><replaceable>expr</replaceable>++
<replaceable>expr</replaceable>-- ()
[] .
?<replaceable>identifier</replaceable></entry>
</row>
<row>
<entry>unary prefix</entry>
<entry class="operatorList">-<replaceable>expr</replaceable>
!<replaceable>expr</replaceable>
~<replaceable>expr</replaceable>
++<replaceable>expr</replaceable>
--<replaceable>expr</replaceable> </entry>
</row>
<row>
<entry>multiplicative</entry>
<entry class="operatorList">* / %
~/</entry>
</row>
<row>
<entry>additive</entry>
<entry class="operatorList">+ -</entry>
</row>
<row>
<entry>shift</entry>
<entry class="operatorList"><< >></entry>
</row>
<row>
<entry>relational and type test</entry>
<entry class="operatorList">>= >
<= < as is
is!</entry>
</row>
<row>
<entry>equality</entry>
<entry class="operatorList">== !=
</entry>
</row>
<row>
<entry>bitwise AND</entry>
<entry class="operatorList">&</entry>
</row>
<row>
<entry>bitwise XOR</entry>
<entry class="operatorList">^</entry>
</row>
<row>
<entry>bitwise OR</entry>
<entry class="operatorList">|</entry>
</row>
<row>
<entry>logical AND</entry>
<entry class="operatorList">&&</entry>
</row>
<row>
<entry>logical OR</entry>
<entry class="operatorList">||</entry>
</row>
<row>
<entry>conditional</entry>
<entry class="operatorList"><replaceable>expr1</replaceable> ?
<replaceable>expr2</replaceable> :
<replaceable>expr3</replaceable></entry>
</row>
<row>
<entry>cascade</entry>
<entry class="operatorList">..</entry>
</row>
<row>
<entry>assignment</entry>
<entry class="operatorList">= *= /=
~/= %= += -=
<<= >>= &=
^= |= </entry>
</row>
</tbody>
</tgroup>
</table>
<para>When you use operators, you create
<glossterm>expressions</glossterm>. Here are some examples of operator
expressions:</para>
<programlisting>a++
a + b
a = b
a == b
a? b: c
a is T</programlisting>
<para>In <xref linkend="operator_table" />, each operator has higher
precedence than the operators in the rows below it. For example, the
multiplicative operator <literal>%</literal> has higher precedence than
(and thus executes before) the equality operator <literal>==</literal>,
which has higher precedence than the logical AND operator
<literal>&&</literal>. That precedence means that the following
two lines of code execute the same way:</para>
<programlisting>if ((n % i == 0) && (d % i == 0)) // Parens improve readability.
if (n % i == 0 && d % i == 0) // Harder to read, but equivalent.</programlisting>
<warning>
<simpara>For operators that work on two operands, the leftmost operand
determines which version of the operator is used. For example, if you
have a Vector object and a Point object, <literal>aVector +
aPoint</literal> uses the Vector version of +.</simpara>
</warning>
<sect2 id="op-arithmetic">
<title>Arithmetic operators</title>
<para>Dart supports the usual arithmetic operators.</para>
<table class="operatorTable" id="arithmetic_operator_table">
<title>Arithmetic operators</title>
<tgroup cols="2">
<thead>
<row>
<entry>Operator</entry>
<entry>Meaning</entry>
</row>
</thead>
<tbody>
<row>
<entry class="operator">+</entry>
<entry>Add</entry>
</row>
<row>
<entry class="operator">–</entry>
<entry>Subtract</entry>
</row>
<row>
<entry class="operator">-<replaceable>expr</replaceable></entry>
<entry>Unary minus, also known as negation (reverse the sign of
the expression)</entry>
</row>
<row>
<entry class="operator">*</entry>
<entry>Multiply</entry>
</row>
<row>
<entry class="operator">/</entry>
<entry>Divide</entry>
</row>
<row>
<entry class="operator">~/</entry>
<entry>Divide, returning an integer result</entry>
</row>
<row>
<entry class="operator">%</entry>
<entry>Get the remainder of an integer division (modulo)</entry>
</row>
</tbody>
</tgroup>
</table>
<para>Example:</para>
<programlisting>var a = 2;
var b = 3;
assert(a + b == 5);
assert(a - b == -1);
assert(a * b == 6);
assert( a / b > 0.6 && a / b < 0.7);
assert(a ~/ b == 0); // Quotient
assert(a % b == 2); // Remainder</programlisting>
<para>Dart also supports both prefix and postfix increment and decrement
operators.</para>
<table class="operatorTable" id="pfix_operator_table">
<title>Increment and decrement operators</title>
<tgroup cols="2">
<thead>
<row>
<entry>Operator</entry>
<entry>Meaning</entry>
</row>
</thead>
<tbody>
<row>
<entry class="operator">++<replaceable>var</replaceable></entry>
<entry><replaceable>var</replaceable> =
<replaceable>var</replaceable> + 1 (expression value is
<replaceable>var</replaceable> + 1)</entry>
</row>
<row>
<entry class="operator"><replaceable>var</replaceable>++</entry>
<entry><replaceable>var</replaceable> =
<replaceable>var</replaceable> + 1 (expression value is
<replaceable>var</replaceable>)</entry>
</row>
<row>
<entry class="operator">--<replaceable>var</replaceable></entry>
<entry><replaceable>var</replaceable> =
<replaceable>var</replaceable> – 1 (expression value is