Conditionals Top Input and OutputFunctions Contents

Functions

Consider the equation to find the y-value of a point on the line:

    y = 5x - 3

First, we assigned values to the slope, the x-value, and the y-intercept:

    (define m 5)
    (define x 9)
    (define b -3)

Once those variables have been created, we can compute the value of y:

    (define y (+ (* m x) b))

    (inspect y)
    -> y is 42

Now, suppose we wished to find the y-value corresponding to a different x-value or, worse yet, for a different x-value on a different line. All the work we did would have to be repeated. A function is a way to encapsulate all these operations so we can repeat them with a minimum of effort.

Encapsulating a series of operations

First, we will define a not-too-useful function that calculates y give a slope of 5, a y-intercept of -3, and an x-value of 9 (exactly as above). We do this by wrapping a function around the sequence of operations above. The return value of this function is the computed y value:

    (define (y)
        (define m 5)
        (define x 9)
        (define b -3)
        (+ (* m x) b) ;the value of this expression is the return value
        )

There are a few things to note. The call to the define function indicates that a variable definition is occurring. The fact that the first argument to define looks like a list indicates that the variable being defined will be bound to a function and that the variable/function name is y, as it is the first member of that list. The formal parameters of the function follow the function name; since there is nothing after the y, we don't need to send any information to this function when we call it. Together, the first line is known as the function signature, which tells you the name of the function and how many values it expects to be sent when called.

The expressions after the function name and formal parameters are called the function body; the body is the code that will be evaluated (or executed) when the function is called. You must remember this: the function body is not evaluated until the function is called.

Finally, the return value of a function is the value of the last expression evaluated. In the above case, the expression is:

    (+ (* m x) b)

Once the function is defined, we can find the value of y repeatedly.

    (y)
    -> 42

    (y)
    -> 42

Because we designed the function to take no values when called, we do not place any values between the parentheses.

Note that when we call the y function again, we get the exact same answer.

The y function, as written, is not too useful in that we cannot use it to compute similar things, such as the y-value for a different value of x. This is because we `hard-wired' the values of b, x, and m, We can improve this function by passing in the value of x instead of hard-wiring the value to 9.

Passing arguments

A hallmark of a good function is that it lets you compute more than one thing. We can modify our y function to take in the value of x in which we are interested. In this way, we can compute more than one value of y. We do this by passing in an argument4, in this case, the value of x.

    (define (y x)
        (define m 5)
        (define b -3)
        (+ (* m x) b)
        )

Note that we have moved x from the body of the function to after the function name. We have also refrained from giving it a value since its value is to be sent to the function when the function is called. What we have done is to parameterize the function to make it more general and more useful. The variable x is now called a formal parameter.

Now we can compute y for an infinite number of x's:

    (y 9)
    -> 42
    
    (y 0)
    -> -3
    
    (y -2)
    -> -13

What if we wish to compute a y-value for a given x for a different line? One approach would be to pass in the slope and intercept as well as x:

 (define (y x m b)
        (+ (* m x) b)
        )

Now we need to pass even more information to y when we call it:

    (y 9 5 -3)
    -> 42
     
    (y 0 5 -3)
    -> -3

If we wish to calculate using a different line, we just pass in the new slope and intercept along with our value of x. This certainly works as intended, but is not the best way. One problem is that we keep on having to type in the slope and intercept even if we are computing y-values on the same line. Anytime you find yourself doing the same tedious thing over and over, be assured that someone has thought of a way to avoid that particular tedium. If so, how do we customize our function so that we only have to enter the slope and intercept once per particular line? We will explore one way for doing this. In reading further, it is not important if you understand all that is going on. What is important is that you know you can use functions to run similar code over and over again.

Creating functions on the fly

Since creating functions is hard work (lots of typing) and Computer Scientists avoid unnecessary work like the plague, somebody early on got the idea of writing a function that itself creates functions! Brilliant! We can do this for our line problem. We will tell our creative function to create a y function for a particular slope and intercept! While we are at it, let's change the variable names m and b to slope and intercept, respectively:

    (define (createLine slope intercept)
        (define (y x)
            (+ (* slope x) intercept)
            )
        y    ; the value of y is returned, y is NOT CALLED!
        )

The createLine function creates a y function and then returns it. Note that this returned function y takes one value when called, the value of x.

So our creative createLine function simply defines a y function and then returns it. Now we can create a bunch of different lines:

    (define a (createLine 5 -3))
    (define b (createLine 6 2))

    (a 9)
    -> 42
    
    (b 9)
    -> 56

    (a 9)
    -> 42

Notice how lines a and b remember the slope and intercept supplied when they were created.5 While this is decidedly cool, the problem is many languages ( for example C, C++, and Java6) do not allow you to define functions that create other functions. Fortunately, Scam, Python, and most functional languages allow this.

While this might seem a little mind-boggling, don't worry. The things you should take away from this are:

lusth@cs.ua.edu


Conditionals Top Input and OutputFunctions Contents