-
Notifications
You must be signed in to change notification settings - Fork 4
/
02_program_structure.txt
900 lines (718 loc) · 29.2 KB
/
02_program_structure.txt
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
:chap_num: 2
:prev_link: 01_values
:next_link: 03_functions
= Program Structure =
In this chapter, we will expand our command of the JavaScript language
beyond the nouns and sentence fragments we've seen so far, to the
point where we can express some meaningful prose.
== Expressions and statements ==
(((grammar)))(((syntax)))(((code,structure
of)))(((grammar)))(((JavaScript,syntax)))In
link:01_values.html#values[Chapter 1], we made some values and then
applied operators to them to get new values. Creating values like this
is an essential part of every JavaScript program, but it is only
a part.
(((literal expression)))A fragment of code that produces a value is
called an _((expression))_. Every value that is written literally
(such as `22` or `"socialism"`) is an expression. An expression
between ((parentheses)) is also an expression (like `(1 + 2)`), as is
a ((binary operator)) applied to two expressions (like `"hello " +
"there!"`) or a unary operator applied to one (like `!true`).
(((nesting,of expressions)))(((human language)))This shows part of the
beauty of a language-based interface. Expressions can nest in a way
very similar to the way subsentences in human languages are nested—a
subsentence can contain its own subsentences, and so on. This allows
us to combine expressions to express arbitrarily complex computations.
(((statement)))(((semicolon)))(((program)))If an expression
corresponds to a sentence fragment, a JavaScript _statement_
corresponds to a full sentence in a human language. A program is
simply a list of statements.
(((syntax)))The simplest kind of statement is an expression with a
semicolon after it. This is a program:
[source,javascript]
----
1;
!false;
----
It is a useless program, though. An ((expression)) can be content to
just produce a value, which can then be used by the enclosing
expression. A ((statement)) stands on its own and amounts to something
only if it affects the world. It could display something on the
screen—that counts as changing the world—or it could change the
internal state of the machine in a way that will affect the statements
that come after it. These changes are called _((side effect))s_ (we'll
see an example of a side effect in the next section!). The statements
in the previous example just produce the values `1` and `true` and
then immediately throw them away. This leaves no impression on the
world at all. When executing the program, nothing observable happens.
(((programming style)))(((automatic semicolon
insertion)))(((semicolon)))In some cases, JavaScript allows you to
omit the semicolon at the end of a statement. In other cases, it has
to be there, or the next ((line)) will be treated as part of the same
statement. The rules for when it can be safely omitted are somewhat
complex and error-prone. In this book, every statement that needs a
semicolon will always be terminated by one. I recommend you do the
same in your own programs, at least until you've learned more about
subtleties involved in leaving out semicolons.
== Variables ==
(((syntax)))(((variable,definition)))(((side effect)))(((memory)))How
does a program keep an internal ((state))? How does it remember
things? We have seen how to produce new values from old values, but
this does not change the old values, and the new value has to be
immediately used or it will dissipate again. To catch and hold values,
JavaScript provides a thing called a _variable_.
[source,javascript]
----
var caught = 5 * 5;
----
(((var keyword)))And that gives us our second kind of ((statement)).
The special word (_((keyword))_) `var` indicates that this sentence is
going to define a variable. It is followed by the name of the
variable, an `=` operator, and an expression.
The previous statement creates a variable called `caught` and uses it
to grab hold of the number that is produced by multiplying 5 by 5.
After a variable has been defined, its name can be used as an
((expression)). The value of such an expression is the value the
variable currently holds. Here's an example:
[source,javascript]
----
var ten = 10;
print(ten * ten);
// → 100
----
(((underscore character)))(((dollar
sign)))(((variable,naming)))Variable names can be any word that isn't
a reserved word (such as `var`). They may not include spaces.
Digits can also be part of variable names—`catch22` is a valid name,
for example—but the name must not start with a digit. A variable name
cannot include punctuation, except for the characters `$` and `_`.
(((var keyword)))A single `var` statement may define multiple
variables. The definitions must be separated by commas.
[source,javascript]
----
var one = 1, two = 2;
print(one + two);
// → 3
----
== Keywords and reserved words ==
(((syntax)))(((implements (reserved word))))(((interface (reserved
word))))(((let keyword)))(((package (reserved word))))(((private
(reserved word))))(((protected (reserved word))))(((public (reserved
word))))(((static (reserved word))))(((void operator)))(((yield
(reserved word))))(((reserved word)))(((variable,naming)))Words with
a special meaning, such as `var`, are _((keyword))s_, and they may not
be used as variable names. There are also a number of words that are
“reserved for use” in ((future)) versions of JavaScript. These are also
officially not allowed to be used as variable names, though some
JavaScript environments do allow them. The full list of keywords and
reserved words is rather long.
[source,text/plain]
----
break case catch class const continue debugger
default delete do else enum export extends false
finally for function if implements import in
instanceof interface let new null package private
protected public return static super switch this
throw true try typeof var void while with yield
----
Don't worry about memorizing these, but remember that this might be
the problem when a variable definition does not work as expected.
== The environment ==
(((standard environment)))The collection of variables and their values
that exist at a given time is called the _((environment))_. When a
program starts up, this environment is not empty. It always contains
variables that are part of the language ((standard)), and most of the
time, it has variables that provide ways to interact with the
surrounding system. For example, in a ((browser)), there are variables
and functions to inspect and influence the currently loaded website
and to read ((mouse)) and ((keyboard)) input.
== Functions ==
indexsee:[application (of functions),function application]
indexsee:[invoking (of functions),function application]
indexsee:[calling (of functions),function application]
(((output)))(((function)))(((function,application)))(((alert
function)))(((message box)))Up until now, every value (numbers,
images, booleans) we have created have been unchanging - even with our
most complicated images, they don't change. Sometimes, we want to be
able to create values that are based on other values. For example, we
might want to make an image where the color could vary, based on how
we wanted to use it. To do this, we create _functions_. A function is
a specification for how to create a value depending on some other
values, which are alternatively called _arguments_ or
_parameters_. Functions can also cause side effects (for example, our
`print` function causes values to be shown on the screen - previously,
we referred to `print` as an operator, to make it analogous to `+` or
`*`, but function is the proper name). Even though they are quite a
bit more sophisticated, functions are values just like numbers,
strings, and images - they can be passed as arguments, stored in
variables, etc.
We define functions with the `function` keyword. For example, the
following code defines the variable `square` to refer to a function
that produces the square of a given number:
[source,javascript]
----
var square = function(x) {
return x * x;
};
print(square(12));
// → 144
----
The `function` keyword is followed by parenthesis, and within those
are a comma-separated list of argument names. When you _apply_ the
function, these names will be where the input values are. The body of
the function (between the `{` and `}`) should eventually produce a
value (it can also do other things first). To produce a value, you use
the `return` keyword. There is a little more about `return` in the
next section.
(((parameter)))(((function,application)))Using a function is
called _invoking_, _calling_, or _applying_ it. You can call a
function by putting ((parentheses)) after an expression that produces
a function value. Usually you'll directly use the name of the variable
that holds the function. We can also define a new name for `square`,
and use that instead:
[source,javascript]
----
var square = function(x) {
return x * x;
};
var my_better_square = square;
print(square(12));
----
Built in functions like `print` can also be given new names:
[source,javascript]
----
var my_better_print = print;
my_better_print("Hello there!");
----
The values between the parentheses are given to the program inside the
function. In the example, the `square` function uses the integer `12`
that we give it as the text to show. Values given to functions are
called _((argument))s_. The `square` function needs only one of them,
but other functions might need a different number or different types
of arguments.
[[return_values]]
== Return values ==
(((comparison,of numbers)))(((return value)))(((Math.max
function)))(((maximum)))Writing text to the screen is a _((side
effect))_. But functions produce values, and these are usually why we
want to use them. For example, the function `Math.max` takes any
number of number values and gives back the greatest.
[source,javascript]
----
print(Math.max(2, 4));
// → 4
----
(((function,application)))(((minimum)))(((Math.min function)))The
value that a function produces is called the _return_ value, and the
function is said to have _returned_ the value. Anything that produces
a value is an ((expression)) in JavaScript, which means function calls
can be used within larger expressions. Here a call to `Math.min`,
which is the opposite of `Math.max`, is used as an input to the plus
operator:
[source,javascript]
----
print(Math.min(2, 4) + 100);
// → 102
----
== Dots in function names ==
(((object)))Though ((variable)) names cannot contain ((period
character))s, `Math.max` clearly has one. This is because `Math.max`
isn't a simple variable. It is actually an expression that retrieves
the `max` ((property)) from the value held by the `Math` variable. We
will go into more detail on this later, but for now, you can use these
identifiers the same way you would your own variables.
== Comments ==
(((readability)))Often, raw code does not convey all the information
you want a program to convey to human readers, or it conveys it in
such a cryptic way that people might not understand it. At other
times, you might just feel poetic or want to include some thoughts as
part of your program. This is what _((comment))s_ are for.
(((slash character)))(((line comment)))A comment is a piece of text
that is part of a program but is completely ignored by the computer.
JavaScript has two ways of writing comments. To write a single-line
comment, you can use two slash characters (`//`) and then the comment
text after it.
(((block comment)))A `//` comment goes only to the end of the line. A
section of text between `/*` and `*/` will be ignored, regardless of
whether it contains line breaks. This is often useful for adding
blocks of information about a file or a chunk of program.
[source,javascript]
----
/*
I first found this number scrawled on the back of one of
my notebooks a few years ago. Since then, it has often
dropped by, showing up in phone numbers and the serial
numbers of products that I've bought. It obviously likes
me, so I've decided to keep it.
*/
var myNumber = 11213;
----
== More functions ==
(((power example)))A function can have multiple parameters or no
parameters at all. In the following example, `makeNoise` does not list
any parameter names, whereas `emphasize` lists two:
[source,javascript]
----
var makeNoise = function() {
print("Pling!");
};
makeNoise();
// → Pling!
var emphasize = function(string) {
return string + "!!!!";
};
print(emphasize("hello there"));
// → hello there!!!!
----
(((return value)))(((return keyword)))(((undefined)))Some functions
explicitly `return` a value, such as `emphasize` and `square`, and some
don't, such as `makeNoise`. A `return` statement determines the value
the function returns. When control comes across such a statement, it
immediately jumps out of the current function and gives the returned
value to the code that called the function. The `return` keyword
without an expression after it will cause the function to return
`undefined`. If there is no `return` statement, your function also
returns `undefined`.
For example:
[source,javascript]
----
var my_function = function() {
};
print(my_function());
----
== Functions for drawing ==
You can create an empty scene with:
[source,javascript]
----
var scene = emptyScene(400,100);
print(scene);
----
And we can place a bicycle on that scene using the `placeImage` function, which is like `overlay` but it takes, additionally, how far from the left and top to place the first over the second image:
[source,javascript]
----
var scene = placeImage(bike, emptyScene(400,100), 0, 30);
print(scene);
----
We can move the bike across the scene:
[source,javascript]
----
print(placeImage(bike, emptyScene(400,100), 0, 30));
print(placeImage(bike, emptyScene(400,100), 100, 30));
print(placeImage(bike, emptyScene(400,100), 200, 30));
print(placeImage(bike, emptyScene(400,100), 300, 30));
----
Instead of just creating those scenes, we can write a function that,
given the position of the bike, draws the scene.
[source,javascript]
----
var draw_bike = function(position) {
return placeImage(bike, emptyScene(400,100), position, 30);
};
print(draw_bike(100));
print(draw_bike(200));
print(draw_bike(300));
----
This looks something like the images in a flip book, right? In a flip book,
each page has a different image and you can view an animation by
flipping the pages in sequence. So lets turn this into an animation!
TLC.js has a function called `animate` that can create animations from
functions like this. It takes a function that returns an image (like our
_draw_bike_). Then it calls that function with the number 0 and draws the
image. It calls it again with 1, and draws that image... and the
same for 2, 3 ,4... And keeps going forever, feeding your function increasing
numbers and drawing the result.
`animate` uses JavaScript's native animation functions that try to draw 60
frames per second. You can think of each frame as one page in the flip
book. The browser's JavaScript engine can only do one thing at a time,
so if there are lots of animations on a page, it will try to draw one frame
from each of them before moving on to the next frame. That's why
webpages with many animations can feel slow and choppy. The time between
frames is longer! That time period is called a "tick", and the number
of ticks since the animation starts is what is passed to the drawing
function in `animate`.
[source,javascript]
----
var draw_bike = function(ticksSinceStart) {
var xPosition = ticksSinceStart;
return placeImage(bike, emptyScene(400,100), xPosition, 30);
};
animate(draw_bike);
----
== A shorter way to define functions ==
Since giving names to functions by storing them in variables is really
common, there is a shorter way to do these two things:
[source,javascript]
----
var name = function(arg) { return arg; };
// Is equivalent to:
function name(arg) { return arg; }
----
The second is a little shorter and doesn't have a semicolon at the end.
== Parameters and scopes ==
(((function,application)))(((variable,from parameter)))The
((parameter))s to a function behave like regular variables, but their
initial values are given by the _caller_ of the function, not the code
in the function itself.
(((function,scope)))(((scope)))(((local variable)))An important
property of functions is that the variables created inside of them,
including their parameters, are _local_ to the function. This means
that any variables defined within functions will be newly created
every time the function is called, and these separate incarnations do
not interfere with each other.
indexsee:[top-level scope,global scope]
(((var keyword)))(((global scope)))(((variable,global)))This
“localness” of variables applies only to the parameters and to variables
declared with the `var` keyword inside the function body. Variables
declared outside of any function are called _global_, because they are
visible throughout the program. It is possible to access such
variables from inside a function, as long as you haven't declared a
local variable with the same name.
(((variable,assignment)))The following code demonstrates this. It
declares the variable as local and thus changes only the local
variable, which is unchanged.
[source,javascript]
----
var x = "outside";
var f1 = function() {
var x = "inside f1";
};
f1();
print(x);
// → outside
----
(((variable,naming)))(((scope)))(((global scope)))(((code,structure
of)))This behavior helps prevent accidental interference between
functions. If all variables were shared by the whole program, it'd
take a lot of effort to make sure no name is ever used for two
different purposes. By treating function-local variables as existing
only within the function, the language makes it possible to read and
understand functions as small universes, without having to worry about
all the code at once.
== Animation ==
_animate_ calls your drawing function with a number. That number
represents how many "ticks" have happened since the animation started.
Note: in the following, we want to turn a number (of ticks) into an
image. We have a function called `text` that takes a string (like
`"hello"`) and turns it into an image. So if we could first take our
number (like `12` and turn it into a string `"12"`), then we could
turn it into an image with text. Javascript has a built in function
that is called `String` that does just that. You can see it in use in
the below example. If you are trying to do the reverse (turn a string
like `"1001"` into the number `1001`), there is a corresponding
function `Number`.
[source,javascript]
----
function show_how_many_ticks(ticksSinceStart) {
return text(String(ticksSinceStart), 16);
}
animate(show_how_many_ticks);
----
This number (corresponding to the annoying linear nature of time as we
conventionally experience it) is always getting bigger at a constant
rate. So it makes sense that we can use it to create an animation of something
growing or moving forward:
[source,javascript]
----
function growingCircle(time) {
var size = time;
return overlay(circle(size, "red"), emptyScene(200, 200));
}
animate(growingCircle);
function movingCircle(time) {
var xPosition = time;
return placeImage(circle(10, "black"), emptyScene(200, 30), xPosition, 5);
}
animate(movingCircle);
----
But while a steady march forward into infinity isn't a terrible
approximation of how we experience changes in time, it's still not a
very useful way to represent how things change shape or
position. Things don't always grow, sometimes they shrink. Things
move backwards as well as forwards. And sometimes they move faster or
slower. How do we take a number that is always getting bigger (the
amount of time that has passed) and turn it into a number that changes
in a different way?
We can think about the different tools we have already. We have lots
of operators: `-`, `+`, `*`, and `/`. We'll also introduce a new
operator, `%` (pronounced "mod"). Let's see what happens when we use
these operators with animate!
Hmmm. All these operators can take two arguments. One of them is
going to be time, but we need another number. This is just an experiment
so lets pick any number... How about 100?
[source,javascript]
----
function adding(time) {
return text("100 + the current time (" + String(time) + ") is " + (100 + time), 16);
}
animate(adding);
----
[source,javascript]
----
function subtracting(time) {
return text("100 - the current time (" + String(time) + ") is " + String(100 - time), 16);
}
animate(subtracting);
----
[source,javascript]
----
function multiplying(time) {
return text("100 * the current time (" + String(time) + ") is " + String(100 * time), 16);
}
animate(multiplying);
----
[source,javascript]
----
function dividing(time) {
return text("100 / the current time (" + String(time) + ") is " + String(100 / time), 16);
}
animate(dividing);
----
Now for the new operator:
[source,javascript]
----
// `%` divides by the number by another number and returns
// the remainder
function modding(time) {
return text("the current time (" + String(time) + ") % 100 is " + String(time % 100), 16);
}
animate(modding);
----
So you can see that the `time` going into the function is always increasing at
the same rate, just like before. But now, some of the resulting numbers are
increasing and some are decreasing, and they are doing that at different rates!
What does that look like when we apply it to images?
[source,javascript]
----
function adding1(time) {
var radius = 100 + time;
return overlay(circle(radius, "red"), emptyScene(200, 200));
}
function adding2(time) {
var xPosition = 100 + time;
return placeImage(circle(10, "black"), emptyScene(200, 30), xPosition, 5);
}
animate(adding1);
animate(adding2);
----
[source,javascript]
----
function subtracting1(time) {
var radius = 100 - time;
return overlay(circle(radius, "red"), emptyScene(200, 200));
}
function subtracting2(time) {
var xPosition = 100 - time;
return placeImage(circle(10, "black"), emptyScene(200, 30), xPosition, 5);
}
animate(subtracting1)
animate(subtracting2);
----
The next two cause changes so fast or so slow that it's hard to
even see.
[source,javascript]
----
function multiplying1(time) {
var radius = time * 100;
return overlay(circle(radius, "red"), emptyScene(200, 200));
}
function multiplying2(time) {
var xPosition = time * 100;
return placeImage(circle(10, "black"), emptyScene(200, 30), xPosition, 5);
}
animate(multiplying1);
animate(multiplying2); // moves so fast you can't even see it!
----
[source,javascript]
----
function dividing1(time) {
var radius = time / 100;
return overlay(circle(radius, "red"), emptyScene(200, 200));
}
function dividing2(time) {
var xPosition = time / 100;
return placeImage(circle(10, "black"), emptyScene(200, 30), xPosition, 5);
}
animate(dividing1);
animate(dividing2); // moves so slow you can hardly tell!
----
Try multiplying and dividing by 10 instead of 100 and see what
happens! Try even smaller numbers and bigger numbers!
[source,javascript]
----
function modding1(time){
var radius = time % 100;
return overlay(circle(radius, "red"), emptyScene(200, 200));
}
function modding2(time){
var xPosition = time % 100;
return placeImage(circle(10, "black"), emptyScene(200, 30), xPosition, 5);
}
animate(modding1);
animate(modding2);
----
Using `%` in animation creates a looping effect! How would you make the
circle in `modding2` go all the way to the end of the box?
== Fluid movement with _sin_ ==
Another fun function for making animations is `Math.sin`. This is the _sin_
function from math. You can fiddle with this to get interesting things to happen:
[source,javascript]
----
function sinWiggle(ticksSinceStart) {
var xPosition = Math.sin(ticksSinceStart/20) * 90 + 90;
return placeImage(circle(10, "black"), emptyScene(200, 30), xPosition, 5);
}
animate(sinWiggle);
----
The cool thing about _sin_ and _cos_ is that `Math.sin(anything)` and
`Math.cos(anything)` are always numbers between -1 and 1.
[source,javascript]
----
print(Math.sin(0));
print(Math.sin(100));
print(Math.sin(500000));
----
If you multiply the result of `sin(some number)`
by 90, you will always get a number between -90 and 90.
[source,javascript]
----
print(Math.sin(0) * 90);
print(Math.sin(100) * 90);
print(Math.sin(500000) * 90);
----
We use that fact in
_sinWiggle_. We multiple by 90 to always get a number between -90 and 90.
Then we add 90, so the number is always between 0 and 180.
[source,javascript]
----
print(Math.sin(0) * 90 + 90);
print(Math.sin(100) * 90 + 90);
print(Math.sin(500000) * 90 + 90);
----
So _sinWiggle_ takes a number, no matter how big, and turns that into an
image placing a dot.
A helpful operator is `%`, which is pronounced _mod_. It takes the
_remainder_ after diving the right side by the left side.
== Control flow ==
(((execution order)))(((program)))(((control flow)))When your program
contains more than one ((statement)), the statements are executed,
predictably, from top to bottom. As a basic example, this program has
two statements.
[source,javascript]
----
print(bike);
print(circle(100, "green"));
----
Here is the rather trivial schematic representation of straight
control flow:
image::img/controlflow-straight.svg[alt="Trivial control flow",width="4cm"]
== Conditional execution ==
(((Boolean)))(((control flow)))Executing statements in straight-line
order isn't the only option we have. An alternative is _((conditional
execution))_, where we choose between two different routes based on a
Boolean value, like this:
image::img/controlflow-if.svg[alt="Conditional control flow",width="4cm"]
(((syntax)))(((Number function)))(((if keyword)))Conditional execution
is written with the `if` keyword in JavaScript. In the simple case, we
just want some code to be executed if, and only if, a certain
condition holds. For example, we can write a function that returns one message if a number is bigger than zero and another if it is smaller!
[source,javascript]
----
var sign = function(number) {
if (number > 0) {
return "it's a positive number";
} else {
return "it's not a positive number";
}
};
print(sign(8));
print(sign(0));
print(sign(-15));
----
If we have more than two paths to choose from, multiple if/else pairs can be “chained” together. We can use that to make our message more informative:
[source,javascript]
----
var sign = function(number) {
if (number > 0) {
return "it's a positive number";
} else if (number === 0) {
return "it's zero";
} else {
return "it's a negative number";
}
};
print(sign(8));
print(sign(0));
print(sign(-15));
----
The flow chart for this program looks something like this:
image::img/controlflow-nested-if.svg[alt="Nested if control flow",width="4cm"]
We can also use this to improve our bike animation. Previously, when
the bike reached the edge of the scene, it kept going. Instead, we can
make it stop!
[source,javascript]
----
var draw_bike = function(position) {
if (position > 300) {
return placeImage(bike, emptyScene(400,100), 300, 30);
} else {
return placeImage(bike, emptyScene(400,100), position, 30);
}
};
animate(draw_bike);
----
== Exercises ==
1. __Magical Teleporting Bike__
Let's try making a magical teleporting bike!
This magical bike rides on the ground for the first part of its journey. When it reaches the carefully guarded, top secret, Original Magic Teleportation Point (known to UFO buffs as Position 80), it jumps up into the sky! When it reaches the next Magical Teleportation Point (known by the initiate as Position 160), it jumps back down to the ground. When it reaches the end of its Magical Road (at the pitstop locals like to call Position 320), it stops.
We've sketched out a skeleton of what a program for creating such a Magical Teleporting Bike might look like below. Try replacing the comments with running code and giving the Magical Teleporting Bike for a spin!
[source,javascript]
----
var draw_bike = function(position) {
if (position < 80) {
return placeImage(bike, emptyScene(400,100), position, 30);
} else if (position < 160) {
// jump to the top!
} else if (position < 320){
// jump back to the bottom!
} else {
// stop!
}
};
animate(draw_bike);
----
2. Make an image you already made move!
In chapter 1, at the end, you may have drawn an image. Now that you
have `animate`, you should be able to make some part (or many parts)
of your image move.
3. __Extra credit: Go Backwards!__
Can you think of a way to replace the comment with code that will make the bike go backwards once it reaches the right-most part of the scene?
[source,javascript]
----
var draw_bike = function(position) {
if (position < 400) {
return placeImage(bike, emptyScene(400, 100), position, 30);
} else {
return placeImage(bike, emptyScene(400, 100), /*what goes here?*/ 30)
};
};
animate(draw_bike);
----
4. __Extra credit: Back and forth forever__
Using `mod`, can you figure out how to make the bike run back and
forth across the screen forever?
== Summary ==
You now know that a program is built out of statements, which
themselves sometimes contain more statements. Statements tend to
contain expressions, which themselves can be built out of smaller
expressions.
Putting statements after one another gives you a program that is
executed from top to bottom. You can introduce disturbances in the
flow of control by using conditional (`if`, `else if`, `else`) statements.
Variables can be used to file pieces of data under a name, and they
are useful for organizing your program. The environment is the
set of variables that are defined. JavaScript systems
always put a number of useful standard variables into your
environment.
Functions are special values that encapsulate a piece of program. You
can invoke them by writing `functionName(argument1, argument2)`. Such
a function call is an expression, and produces a value.