September 18 – 21

September 18

We reviewed material that will be on the Lab Exam 1. See Lab Exam 1 Study Guide

Mainly, today we introduced functions. Not just calling functions (such as rect). Not just defining function (such as draw). We introduced

  • Inventing your own concept or abstraction.
  • Defining your own function to implement that concept.
  • Calling your function.

To get started, here’s a “house” program:

house

// Draw a house

function setup() {
    createCanvas(200, 150);
}

function draw() {
    background(150, 200, 150);
    triangle(50, 50, 100, 25, 150, 50);
    rect(60, 50, 80, 50)
    rect(100, 65, 15, 35);
    rect(75, 65, 15, 15);
    noLoop(); // no need to draw again
}

Now, we’ll call house() in draw() and define the function house() to do the work. The output is the same:

function definition

function setup() {
    createCanvas(200, 150);
}

function draw() {
    background(150, 200, 150);
    house();
    noLoop(); // no need to draw again
}

function house() {
    triangle(50, 50, 100, 25, 150, 50);
    rect(60, 50, 80, 50)
    rect(100, 65, 15, 35);
    rect(75, 65, 15, 15);
}

We can go further, defining a function to compute each sub-part of the house. Warning: Do not make a function called window because window is already used by p5js.

functions calling functions

function setup() {
    createCanvas(200, 150);
}

function draw() {
    background(150, 200, 150);
    house();
    noLoop(); // no need to draw again
}

function house() {
    roof();
    room();
    door();
    windows();
}

function roof() {
    triangle(50, 50, 100, 25, 150, 50);
}

function room() {
    rect(60, 50, 80, 50);
}

function door() {
    rect(100, 65, 15, 35);
}

function windows() {
    rect(75, 65, 15, 15);
}

Parameters

We call the actual values you list between parentheses when you call a function arguments. When you call point(20, 50), the arguments are 20 and 50.

When you define a function, you can provide parameters which act just like new local variables that are initialized to the arguments provided by the caller. Read this sentence again. It’s important! Here’s an example where we define house with location parameters x and y.

moving house

function setup() {
    createCanvas(200, 150);
}

function draw() {
    background(150, 200, 150);
    house(mouseX, mouseY);
    frameRate(10);
}

function house(x, y) {
    triangle(x, y, x + 50, y - 25, x + 100, y);
    rect(x + 10, y, 80, 50)
    rect(x + 50, y + 15, 15, 35);
    rect(x + 25, y + 15, 15, 15);
}

Notice that I replaced noLoop() with frameRate(10). (I used a low frame rate and small canvas to save power – I could have left all these examples drawing big pictures at 60 frames per second, but at least on my machine, that takes a noticeable amount of power – I hear the cooling fans come on – and it’s really not necessary for examples like this.)

Notice also that I can use mouseX and mouseY as arguments. Now without editing the house() code, I can use house as a “concept” just like rect or ellipse.

Write a loop to draw 10 houses using the house function.

September 21

syntax

We talked about syntax — the structure of the text that represents a program.

Programming language syntax is described by formal grammars. Here “formal” means precise or mathematical as opposed to, say, grammars for natural languages such as English, which has no precise or formal definition.

A simple grammar for numbers can be described using a meta-language (a language that describes a language!). In the metalanguage, ::= means the thing on the left can be replaced by the pattern on the right. The vertical bar (|) means choose either of two patterns. Brackets [ ] enclose optional elements.

number ::= digit | number digit
digit ::= 0 | 1 | 2 | … | 9

Using these rules, you can create all strings of digits. E.g. this figure shows how repeated substitutions for number and digit can end with the number 123:

number-grammar

We can use formal grammars like this to describe what constitutes a JavaScript program.

The rule for if statements is:

ifstmt ::= if ( expression ) statement [ else statement ]

Notice that no braces { } are required. Where do braces come in? When are braces permitted? There is a compound statement:

compoundstatement ::= { statement [ ; statement [ ; …]] )

Any place a statement is allowed, you can substitute a compound statement. Notice this explains semicolons as well: semicolons are merely statement separators in compound statements.

What’s an expression? Here’s a partial rule:

expression ::= expression op expression | ( expression ) | name = expression | unaryoperator expression | name ( parameterlist )
op ::= + | – | * | / | | = | == | === | != | !== | % | …

Notice that any expression can be enclosed in parentheses as shown by ( expression ).

What’s the point of all this?

  • There are relatively few rules that can “generate” infinitely many programs.
  • All expressions have the same syntax and follow the same rules.
  • Similarly, all statements are the same (but like expressions, they are recursively defined.
  • Different programming languages have different syntax, but by learning that programs are constructed from relatively simple rules, you’ll be able to learn new programming languages once you learn JavaScript and it’s principles.

Returning values from functions

This example uses a function to compute if a point (x, y) is inside a rectangle (given by left, top, width, height):

sketch


function setup() {
    createCanvas(100, 100);
    print("foo" === "foo");
}

function draw() {
    background(200, 240, 250);
    // inBox() is our function that evaluates to 
    //    true or false in the following if stmt:
    if (inBox(mouseX, mouseY, 25, 25, 50, 50)) {
        fill(255, 0, 0);
    }
    rect(25, 25, 50, 50);
}

// determine if point (x,y) is in box (left,top,w,h):
function inBox(x, y, left, top, w, h) {
    var inside = (x > left && x < left + w &&
                  y > top && y < top + h);
    // "return" statements stop the function execution,
    // resume processing where the function was called,
    // and specify the value of the function:
    return inside;
}

This example uses functions to compute force in the x and y directions:

sketch

var x = 100;  // x position
var y = 100;  // y position
var xvel = 0; // x velocity
var yvel = 0; // y velocity

function setup() {
    createCanvas(300, 300);
    frameRate(30);
}

function draw() {
    background(200, 240, 250);
    fill(255, 0, 0);
    ellipse(x, y, 20, 20);
    // velocity is updated by force
    xvel = xvel + xforce(x, y);
    yvel = yvel + yforce(x, y);
    // position is updated by velocity
    x = x + xvel;
    y = y + yvel;
}

function xforce() {
    var xf = mouseX - x; // mouse attracts
    xf = xf + -xvel * 5; // frictional force increases with velocity
    return xf / 500;
}

function yforce() {
    var yf = mouseY - y;
    yf = yf + -yvel * 5;
    return yf / 500;
}