Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Add a third lesson, functions and flow control

  • Loading branch information...
commit 430217f4c4a4996e6e413089f7d1614b44e559ca 1 parent b34ddd7
Siddharth Mahendraker authored November 23, 2012

Showing 1 changed file with 380 additions and 0 deletions. Show diff stats Hide diff stats

  1. 380  lessons/03-functions.js
380  lessons/03-functions.js
... ...
@@ -0,0 +1,380 @@
  1
+/*
  2
+ * Let's start with a quick review of what we've learned so far:
  3
+ *
  4
+ * 1. Variables are created using the var keyword, and allow us to store,
  5
+ * retrieve and manipulate data.
  6
+ * 2. The data variables hold comes in different types, called data types.
  7
+ * 3. Data types separate different kinds of data so that we can deal with
  8
+ * them properly.
  9
+ * 4. Data types have certain properties which we can access using the dot
  10
+ * (.) operator.
  11
+ *
  12
+ * Keeping this in mind, let's learn a little more about functions.
  13
+ *
  14
+ * So far, we have only dealt with executing functions, for example:
  15
+ *
  16
+ * console.log("Hey");
  17
+ *
  18
+ * It turns out, that functions are actually a special kind of "data type",
  19
+ * which can actually be manipulated just like any other variable.
  20
+ *
  21
+ * For now, we're going to define functions in the following way. As we
  22
+ * progress, we will learn new ways of defining functions that are perhaps
  23
+ * less cumbersome.
  24
+ *
  25
+ * var fn = function(param1, param2, param3){
  26
+ *
  27
+ *     // ...
  28
+ *     // Let the function to it's thing
  29
+ *     // ...
  30
+ *
  31
+ *     return returnValue;
  32
+ * }
  33
+ *
  34
+ * Notice the keyword "return someExpression". This tells the function when
  35
+ * it is done executing and what it should return as a return value. If
  36
+ * there is no return value, functions will default to returning "undefined".
  37
+ *
  38
+ * In the example above, the function "fn" can be executed, or called, as
  39
+ * follows:
  40
+ *
  41
+ * var value = fn(p1, p2, p3);
  42
+ *
  43
+ * Note that the "var value =" portion of the code is only necessary if you
  44
+ * want to keep the return value of fn. If not, fn could be called like
  45
+ * this:
  46
+ *
  47
+ * fn(p1, p2, p3);
  48
+ *
  49
+ * The most important part of functions, however, is what actually happens
  50
+ * inside them. Data flowing into functions must be manipulated in some way
  51
+ * or another before anything useful can be obtained. Most often, we will
  52
+ * require some way of telling the computer to execute one function if
  53
+ * the input matches certain criteria, and another function if the
  54
+ * input does not.
  55
+ *
  56
+ * This is called a conditional structure or expression, and looks something
  57
+ * like this:
  58
+ *
  59
+ * if(a > b){
  60
+ *     runThisFunction(a, b);
  61
+ * }else{
  62
+ *     runThatFunction(b, a);
  63
+ * }
  64
+ *
  65
+ * The above code tells the computer to execute "runThisFunction" when
  66
+ * a is greater than b, or execute "runThatFunction" if that condition is
  67
+ * not met.
  68
+ *
  69
+ * In javascript, there are several other comparison operators used mainly
  70
+ * in conditional expressions. Like their math counterparts, they behave
  71
+ * more or less as you would expect. They are:
  72
+ *
  73
+ * > (greater than), < (less then), >= (greater than or equal),
  74
+ * <= (less than or equal), === (equal)
  75
+ *
  76
+ * These operators can essentially be thought of as functions which return
  77
+ * a special data type, called a boolean. A boolean is either a true or a
  78
+ * false value. For example, all of the following variables are boolean:
  79
+ *
  80
+ * var isMale = true;
  81
+ * var isFemale = false;
  82
+ *
  83
+ * Therefore, you can also insert functions into conditional statements,
  84
+ * so long as the function returns a boolean value.
  85
+ *
  86
+ * if(isCookies(food)){
  87
+ *     eat(food);
  88
+ * }else{
  89
+ *     console.log("Give me cookies!");
  90
+ * }
  91
+ *
  92
+ * This means that somewhere in the code, isCookies must be defined
  93
+ * as:
  94
+ *
  95
+ * var isCookies = function(item){
  96
+ *     // Do your magic...
  97
+ *     return true; // or false
  98
+ * }
  99
+ *
  100
+ *
  101
+ * Let's take a look at the following (fairly stupid) example which ties
  102
+ * together all of these concepts, before moving on to some more interesting
  103
+ * stuff.
  104
+ */
  105
+
  106
+var isLessThanOne = function(x){
  107
+    if(x < 1){
  108
+        return true;
  109
+    }else{
  110
+        return false;
  111
+    }
  112
+}
  113
+
  114
+/*
  115
+ * This code defines a function, called "isLessThanOne", which returns true
  116
+ * if it's input x is less than 1 and false otherwise.
  117
+ *
  118
+ * Note that because the return keyword stops the execution of functions,
  119
+ * isLessThanOne could also be defined as:
  120
+ *
  121
+ * var isLessThanOne = function(x){
  122
+ *     if(x < 1){
  123
+ *         return true;
  124
+ *     }
  125
+ *
  126
+ *     return false;
  127
+ * }
  128
+ *
  129
+ * The conditional expression introduced above is actually the most common
  130
+ * of several flow control structures used in javascript.
  131
+ *
  132
+ * Flow control structures, as you may have guessed from the name, are used
  133
+ * to change the flow of a program. Instead of having to execute all of your
  134
+ * code linearly, flow control structures allow the computer to jump around
  135
+ * from one place in the code to another. In that sense, functions can also
  136
+ * be thought of as flow control structures because they enable the
  137
+ * computer to execute the program in a non-linear fashion.
  138
+ *
  139
+ * The next most important flow control structure is the loop. Loops allow
  140
+ * you to tell the computer to do a certain task over and over again, until
  141
+ * a certain criteria is met. In javascript loops are defined as:
  142
+ *
  143
+ * for(var i = 0; i < posNum; i++){
  144
+ *     // The body of the loop
  145
+ * }
  146
+ *
  147
+ * This kind of loop is called a "for" loop.
  148
+ *
  149
+ * The most interesting part of a loop occurs in between the parentheses,
  150
+ * after the "for":
  151
+ *
  152
+ * (var i = 0; i < posNum; i++)
  153
+ *
  154
+ * The first statement, before the first ";", defines a variable. The
  155
+ * second statement defines the conditional expression that will be
  156
+ * evaluated every time the loop completes to check if it should keep going,
  157
+ * and the third statement is the code executed after each loop completes.
  158
+ *
  159
+ * Notice the "i++" expression in the third statement. The "++" expression
  160
+ * is a short hand for i = i + 1, which would also be acceptable. Basically,
  161
+ * it increments i by 1.
  162
+ *
  163
+ * Loops sound bad, but they're actually really easy. As usual, it's best to
  164
+ * learn using examples. The following code loops from 1 to 9, and prints
  165
+ * the value of each number in between (including 1 and 9):
  166
+ *
  167
+ * for(var number = 1; number < 10; number++){
  168
+ *     console.log(number);
  169
+ * }
  170
+ *
  171
+ * Let's analyze this code as the computer would, and it might make a little
  172
+ * more sense.
  173
+ *
  174
+ * First, we create a variable called number and assign it the value 1. Then
  175
+ * we check the conditional statement. Is number < 10? Of course it is,
  176
+ * because we just set it to 1.
  177
+ *
  178
+ * Now we execute the body of the loop and print 1. One cycle of the
  179
+ * loop has now been completed.
  180
+ *
  181
+ * This means we need to execute the third statement, which tells us to
  182
+ * increment the value of number by 1.
  183
+ *
  184
+ * Since the earlier condition wasn't met in this cycle, we need to continue
  185
+ * looping.
  186
+ *
  187
+ * Now we're at the beginning of the second loop. This means we need to
  188
+ * check the conditional statement to see if we still need to keep going.
  189
+ * Note that this process will only stop when number === 10, at which point
  190
+ * number will not be less than 10, and the loop will stop executing.
  191
+ *
  192
+ * The structure of a loop can be summarized as follows:
  193
+ *
  194
+ * Begin loop ---> Define variable
  195
+ *                      |
  196
+ *                      |
  197
+ *              --->  Check condition ---
  198
+ *              |                       |
  199
+ *              |                       |
  200
+ *              ---   Execute body   <---
  201
+ *                      |
  202
+ *                      |
  203
+ * End loop  <-- Condition fails
  204
+ *
  205
+ * Now that we've (hopefully) understood all of that, let's make a program
  206
+ * which uses these components in an interesting way ;)
  207
+ *
  208
+ */
  209
+
  210
+var fib = function(n){
  211
+    if(isLessThanOne(n)){
  212
+        // You can't have negative Fibonacci numbers
  213
+        return 0;
  214
+    }
  215
+
  216
+    // Create variables to hold the 0th and 1st Fibonacci numbers
  217
+    var prevNum = 0,
  218
+        currNum = 1;
  219
+
  220
+    // console.log(currNum);
  221
+
  222
+    // Find the nth Fibonacci number by iterating the formula n-1 times
  223
+    for(var i = 0; i < (n - 1); i++){
  224
+        // The next Fibonacci number is always the sum of the
  225
+        // previous two
  226
+        var nextNum = prevNum + currNum;
  227
+
  228
+        // Set the variable holding the Fibonacci number two steps
  229
+        // back to the current Fibonacci number
  230
+        prevNum = currNum;
  231
+        // Update the current Fibonacci number to the value of the
  232
+        // next Fibonacci number
  233
+        currNum = nextNum;
  234
+
  235
+        // console.log(currNum);
  236
+    }
  237
+
  238
+    // Return the current number
  239
+    return currNum;
  240
+}
  241
+
  242
+var fibNum = fib(10);
  243
+console.log("The 10th Fibonacci number is " + fibNum);
  244
+
  245
+/*
  246
+ * Let's run this program and step through it line by line.
  247
+ *
  248
+ * var fib = function(n){
  249
+ *     if(isLessThanOne(n)){
  250
+ *         // You can't have negative Fibonacci numbers
  251
+ *         return 0;
  252
+ *     }
  253
+ *
  254
+ * By now this should be familiar. We're defining a function called fib,
  255
+ * which takes one parameter "n".
  256
+ *
  257
+ * The first thing we do is use our previous function isLessThanOne
  258
+ * to check if n is less than 1 or not. If n < 1, then isLessThanOne will
  259
+ * return true, and the code inside the if statement will be executed, if
  260
+ * not, the function will continue on as usual.
  261
+ *
  262
+ * Note that if n really is less than 1, for example -3, then the Fibonacci
  263
+ * sequence doesn't really work, and therefore we cannot allow such values.
  264
+ * In real code, you would not return 0, but rather throw an error, which we
  265
+ * will talk about later.
  266
+ *
  267
+ *   // Create variables to hold the 0th and 1st Fibonacci numbers
  268
+ *   var prevNum = 0,
  269
+ *       currNum = 1;
  270
+ *
  271
+ * Next, we initialize some variables to maintain some state inside our
  272
+ * function. Namely, to keep track of the previous and current Fibonacci
  273
+ * numbers. These, as you know, are required to generate the next Fibonacci
  274
+ * number and so on.
  275
+ *
  276
+ * Note the way they were declared. This practise of declaring several
  277
+ * variables in one statement is very common. Note that if you do this, you
  278
+ * must assign these variables values immediately.
  279
+ *
  280
+ * The next few lines are where things get a little hairy:
  281
+ *
  282
+ *   // Find the nth Fibonacci number by iterating the formula n-1 times
  283
+ *   for(var i = 0; i < (n - 1); i++){
  284
+ *       // The next Fibonacci number is always the sum of the
  285
+ *       // previous two
  286
+ *       var nextNum = prevNum + currNum;
  287
+ *
  288
+ *       // Set the variable holding the Fibonacci number two steps
  289
+ *       // back to the current Fibonacci number
  290
+ *       prevNum = currNum;
  291
+ *       // Update the current Fibonacci number to the value of the
  292
+ *       // next Fibonacci number
  293
+ *       currNum = nextNum;
  294
+ *
  295
+ *       // console.log(currNum);
  296
+ *   }
  297
+ *
  298
+ * The first line sets up a for loop which continues until i < (n-1),
  299
+ * and increments i by 1 after each cycle. Now, keep in mind that the
  300
+ * code inside the loop is going to be executed several times in a row.
  301
+ *
  302
+ * The first thing we do is create a variable called nextNum to hold the
  303
+ * next Fibonacci number, which is the sum of the two previous Fibonacci
  304
+ * numbers, in this case prevNum and currNum.
  305
+ *
  306
+ * At this point, we don't need to keep track of the number prevNum is
  307
+ * referring too because all we care about is finding the next Fibonacci
  308
+ * number, which can be created using the values in nextNum and currNum.
  309
+ *
  310
+ * Now, we need to update currNum to have the same value as nextNum, however
  311
+ * because in the next cycle of the loop we're going to be adding currNum
  312
+ * again, we need to make sure it's value isn't lost. So we store the value
  313
+ * of currNum in prevNum and update the value of currNum as desired.
  314
+ *
  315
+ * Repeating this procedure, we eventually arrive at a cycle where i = n - 1,
  316
+ * at which point, we have cycled through n Fibonacci numbers (don't forget
  317
+ * that the initial configuration of currNum is the first Fibonacci number).
  318
+ *
  319
+ * At this point, it is trivial to see that currNum contains the value of
  320
+ * the last Fibonacci number computed, which we promptly return.
  321
+ *
  322
+ *   // Return the current number
  323
+ *   return currNum;
  324
+ *
  325
+ * The correctness of this procedure can also be rigorously proven if
  326
+ * necessary.
  327
+ *
  328
+ * The key to designing this procedure was understanding how to maintain
  329
+ * state throughout, and properly manage variables. You'll soon discover
  330
+ * this is a common theme in computer. In fact, this process is called
  331
+ * maintaining an invariant. Perhaps we will talk about this in later
  332
+ * lessons.
  333
+ *
  334
+ * I realize that this is a larger lesson than usual, but trust me, it's
  335
+ * good to be exposed to these ideas as soon as possible. Once again, the
  336
+ * best way to improve your understand is to practise!!
  337
+ *
  338
+ * Here are a few questions to stimulate your thought:
  339
+ *
  340
+ * 1. Create a function which solves quadratic equations. The function
  341
+ * should begin like this:
  342
+ *
  343
+ * var solver = function(a, b, c){
  344
+ *     // Insert code here
  345
+ * }
  346
+ *
  347
+ * Now solve the quadratic equation ax^2 + bx + c = 0, where a = 9, b = 3
  348
+ * and c = -2 using this method.
  349
+ *
  350
+ * 2. Describe the problem with the following code snippet without running
  351
+ * it. Use your knowledge of for loops.
  352
+ *
  353
+ * var k = 50;
  354
+ *
  355
+ * for(var i = 0; k < 100; i++){
  356
+ *     console.log(i);
  357
+ * }
  358
+ *
  359
+ * console.log("Done!");
  360
+ *
  361
+ * Apply the necessary modification to this code and run it. It should print
  362
+ * the numbers from 0 to 99.
  363
+ *
  364
+ * 3. The modulo operator (%) allows you to test whether a number A is a
  365
+ * multiple of B. If the operation returns 0, then A is a multiple of B.
  366
+ * If not, then A is not a multiple of B. For example: 2 % 5 !== 0,
  367
+ * whereas 25 % 5 === 0.
  368
+ *
  369
+ * Write a program which prints the numbers from 1 to 100 (inclusively).
  370
+ * However, print "Foo" instead of every multiple of 3, "Bar"
  371
+ * instead of every multiple of 5, and "FooBar" for every multiple of
  372
+ * 3 and 5.
  373
+ *
  374
+ * Ergo, instead of printing 3, you would print "Foo", instead of printing
  375
+ * 10 you would print "Bar" and instead of printing 15, you would print
  376
+ * "FooBar".
  377
+ *
  378
+ */
  379
+
  380
+

0 notes on commit 430217f

Please sign in to comment.
Something went wrong with that request. Please try again.