## Chapter 5: Functions

## Chapter Goals

- To be able to program functions and procedures
- To become familiar with the concept of parameter passing
- To recognize when to use value and reference passing
- To appreciate the importance of function comments
- To be able to determine the scope of variables
- To minimize the use of side effects and global variables
- To develop strategies for decomposing complex tasks into simpler ones
- To document the responsibilities of functions and their callers with preconditions

## Functions as Black Boxes

- A function is a piece of code assigned to a name.
  - `sqrt()` -- computes the square root of a floating point number
  - `getline()` -- reads a line from the stream
- F unctions can be thought of as black boxes - you don't need to know the internals of the code.
- The execution of `main()` is temporarily suspended while a function is running.

## Functions as Black Boxes

- Many functions have input values or parameters that are transferred or passed into the function.
  - The `x` in `y = sqrt(x);`
  - Both the `x` and the `y` in `z = pow(x, y);`
  - Could be an expression as in `sqrt(b * b - 4 * a * c);`
- Many functions have output or return values.
  - The `y` in `y = sqrt(x);`
- Both parameters and return values are a particular type.
  - You cannot compute `sqrt("Harry");`
  - You cannot assign `string s = sqrt(5.5);`

## Writing Functions (Syntax 5.1 : Function Definition)

Syntax 5.1 : Function Definition
    return_type function_name(parameter1, ..., parametern)
    {
       statements
    }
Example: |
    double abs(double x)
    {
       if (x >= 0) return x;
       else return -x;
    }
Purpose: | Define a functions and supply its implementation.

## Writing Functions (Syntax 5.1 : Function Definition)

- To create a function, we must supply its name, return type, and a list of parameters and their names.

  >     double future_value(double p)

- For the duration of the function, the parameter is stored in a parameter variable (in this example, `p`).
- The body of the function is delimited by braces (just like `main()`):

  >     double future_value(double p)
  >     {
  >        . . .
  >     }

- Code is included to perform the computation. The result is returned to the caller function.

  >     double future_value(double p)
  >     {
  >        double b = 1000 * pow(1 + p / 100, 10);
  >        return b;
  >     }

## Writing Functions (`futval.cpp`)

## Writing Functions (Hard Wired Values)

- The `future_value` function in `futval.cpp` is flawed because the starting amount of the investment and the number of years are hard-wired.
- Hard-wiring prevents reuse of functions:
  - Computing the balance after 20 years.
  - Computing the balance with a different interest rate.
- We avoid hard-wiring values into functions by passing them in as additional parameters.
- Functions are more valuable when they are reusable.

>     double future_value(double initial_balance, double p, int n)
>     {
>        double b = initial_balance * pow(1 + p / 100, n);
>        return b;
>     }

## Function Comments

- We must comment every function, even if it seems silly.
- Comments are for human readers, not compilers.
- There is no universal standard for comment layout, but this book uses the javadoc style.
  - An `@param` entry explaining each parameter
  - An `@return` entry describing the return value
- Comments do not explain the implementation, but the idea.
- Writing comments first, before writing the function code, to test your understanding of what you need to program.

## Function Comments

>     /**
>        Computes the value of an investment with compound interest.
>        @param intial_balance the initial value of the investment
>        @param p the interest rate pre period in percent
>        @param n the number of periods the investment is held
>        @return the balance after n periods
>     */
>     double future_value(double initial_balance, double p, int n)
>     {
>        double b = initial_balance * pow(1 + p / 100, n);
>        return b;
>     }

## Return Values (Syntax 5.2 : `return` Statement)

Syntax 5.3 : `return` Statement
    return expression;
Example: |
    return pow(1 + p / 100, n);
Purpose: | Exit a function, returning the value of the expression as the function result.

## Return Values

- When the return statement is processed, the function exits immediately.

  >     double future_value(double initial_balance, double p, int n)
  >     {
  >        if (n < 0) return 0;
  >        if (p < 0) return 0;
  >        double b = initial_balance * pow(1 + p / 100, n);
  >        return b;
  >     }

- It is important that every branch of a function return a value.

  >     double future_value(double initial_balance, double p, int n)
  >     {
  >        if (p >= 0)
  >           return = initial_balance * pow(1 + p / 100, n);
  >        /* Error */
  >     }

- Functions that returns a truth value is called a predicate.

  >     bool approx_equal(double x, double y)
  >     {
  >        const double EPSILON = 1E-14;
  >        if (x == 0) return fabs(y) <= EPSILON;
  >        if (y == 0) return fabs(x) <= EPSILON;
  >        return fabs(x - y) / max(fabs(x), fabs(y)) <= EPSILON;
  >     }

## Return Values (`approx.cpp`)

## Parameters

- When a function starts, its parameter variables are initialized with the expressions in the function call.

  >     b = future_value(total / 2, rate, year2 - year1);

- It is entirely legal to modify the values of the parameter variables later.

  >     double future_value(double, initial_balance, double p, int n)
  >     {
  >        p = 1 + p / 100;
  >        double b = initial_balance * pow(p, n);
  >        return b;
  >     }

- Many programmers consider this practice bad style.

## Parameters (Syntax 5.3 : Function Declaration (or Prototype))

Syntax 5.3 : Function Declaration (or Prototype)
    return_type function_name(parameter1, ..., parametern);
Example: |
    double abs(double x);
Purpose: | Declare a function so that it can be called before it is defined.

- Function declaration resolves compiler confusion that can arise when one function calls another.
- It also makes programs easier to read.

## Side Effects

- An externally observable effect of a function is called a side effect.
  - Displaying characters on the screen (including error messages).
  - Updating variables outside the functions.
  - Terminating the program.
- A function should leave no trace of its existence except for returning a value.
- Functions that print values become worthless in certain situations.
  - Graphics programs that have no output streams.
  - Programs where the user's language is not English.
  - Programs that don't want to print the value!
- Ideally, a function computes a single value and has no other side effect.

## Procedures

- A function without a return value is called a procedure.

  >     print_time(now);

- The missing return value is indicated by the keyword `void`.

  >     void print_time(Time t)
  >     {
  >        cout << t.get_hours() << ":";
  >        if (t.get_minutes() < 10) cout << "0";
  >        cout << t.get_minutes() << ":";
  >        if (t.get_seconds() < 10) cout << "0";
  >        cout << t.get_seconds();
  >     }

- Since a procedure does not have a return value, it must have a side effect.
- Ideally, a procedure has only one side effect.

## Procedures (`printime.cpp`)

## Reference Parameters

- The parameter variables we have looked at so far are called value parameters.
- Value parameters are separate variables from the ones in `main()` (or another calling function).
- Modification of value parameters does not affect the original value.
- A reference parameter does not create a new variable, but refer to an existing variable.
- Any change in a reference parameter is actually a change in the variable to which it refers.
- Reference parameters are indicated using an `&` between the parameter's type and name.

  >     void raise_salary(Employee& e, double by)
  >     {
  >        double new_salary = e.get_salary() * ( 1 + by / 100);
  >        e.set_salary(new_salary);
  >     }

## Reference Parameters (Syntax 5.4 : Reference Parameters)

Syntax 5.4 : Reference Parameters
    type_name& parameter_name
Example: |
    Employee& e
    int& result
Purpose: | Define a parameter that is bound to a variable in the function call, to allow the function to modify that variable.

## Reference Parameters (`raisesal.cpp`)

## Reference Parameters (Syntax 5.5 : Constant Reference Parameters)

Syntax 5.5 : Constant Reference Parameters
    const type_name& parameter_name
Example: |
    const Employee& e
Purpose: | Define a parameter that is bound to a variable in the function call, to avoid the cost of copying the variable into the parameter variable.

- Reference parameters are more efficient than value parameters because they do not make copies of the parameters.
- Passing variables by constant reference improves performance, but prevents the function from changing the value of the parameter.
- Objects make good constant reference parameters because they tend to have several attributes that need to be copied. Passing numbers by constant reference is generally not worth the effort.

## Variable Scope and Global Variables (Variable Scope)

- You can have variables with the same name in different functions.
- The part within a program in which a variable is visible is known as the scope of the variable.
- The scope of a variable extends from its definition to the end of the block in which it was defined.
- Example:

  >     double future_value(double initial_balance, double p, int n)
  >     {
  >        double r = intial_balance * pow(1 + p / 100, n);
  >        return r;
  >     }

  >     int main()
  >     {
  >        cout << "Please enter the interest rate in percent: ";
  >        double r;
  >        cin >> r;

  >        double balance = future_value(10000, r, 10);
  >        cout << "After 10 years the balance is" << balance
  >           << "\n";

  >        return 0;
  >     }

## Variable Scope and Global Variables (Global Variables)

- Global variables are variables that are defined outside functions.
- A global variable is visible to all functions that are defined after it.
- Sometimes global variables cannot be avoided (`cin`, `cout`, and `cwin`), but you should make every effort to avoid global variables in your program.

## Variable Scope and Global Variables (`global.cpp`)

## Stepwise Refinement

- One of the most powerful strategies for problem solving is the process of stepwise refinement.
- To solve a difficult task, break it down into simpler tasks; then keep breaking down the simpler tasks into even simpler ones, until you are left with tasks that you know how to solve.
- How do you get coffee?
  - Ask someone else to do it.
  - Make coffee.
- OK, how do you make coffee?
  - Make instant coffee.
  - Brew Coffee.
- How do you make instant coffee?

- Start by boiling water.
- Etc.

## From Pseudocode to Code

- Before starting to program, we need to have a plan.
- Any time you need something more than once, it's a good idea to turn that into a function..
- Rather than writing the entire function, begin by writing the comments.
- Example: Writing the function

  >     /**
  >        Turns a number into its English name.
  >        @param n a positive integer < 1,000,000
  >        @return the name of n (e.g. "two hundred seventy four"
  >     */
  >     string int_name(int n);

## From Pseudocode to Code

- Break the problem into sub-tasks and design subprograms.

  >     /**
  >        Turns a digit into its English name
  >        @param n an integer between 1 and 9
  >        @return the name of n ("one" ... "nine")
  >     */
  >     string digit_name(int n);

  >     /**
  >        Turns a number between 10 and 19 into its English name.
  >        @param n an integer between 10 and 19
  >        @return the name of n ("ten"..."nineteen")
  >     */
  >     string teen_name(int n);

  >     /**
  >        Gives the English name of a multiple of 10
  >        @param n an integer between 2 and 9
  >        @return the name of 10 * n ("twenty"..."ninety")
  >     */
  >     string tens_name(int n);

- What is missing?
  - For hundreds, we show the digit name then write "hundreds".
  - For 100 - 999, we can put calls to functions above together to write number.
  - For numbers over 1,000, we call functions above to write the number of thousands, print "thousands", then call the above functions again to write the rest of the number.

## From Pseudocode to Code

- When algorithms are complicated, we first write them as pseudocode.
- Pseudocode is somewhere between C++ and English.

  >     string int_name(int n)
  >     {
  >       int c = n; /* the part that needs to be converted */
  >       string r; /* the return value */

  >       if (c >= 1000)
  >       {
  >           r = name of thousands in c + "thousand"
  >           remove thousands from c
  >       }

  >       if (c >= 100)
  >       {
  >           r = r + name of hundreds in c + "hundreds"
  >           remove hundreds from c
  >       }

  >       if (c >= 20)
  >       {
  >           r = r + name of tens in c
  >           remove tens from c
  >       }

  >       if (c >= 10)
  >       {
  >           r = r + name of c
  >           c = 0
  >       }

  >       if (c > 0)
  >           r = r + name of c;

  >       return r;
  >     }

## From Pseudocode to Code (`intname.cpp`)

## From Pseudocode to Code

- Pseudocode can be easier to understand than a verbal description.
- It's best not to muddy the pseudocode with minor details.
- The pseudocode did not take into account spaces between the words.
- Note that the helper functions needed to be declared before the `int_name` function.
- The `int_name` function calls itself (called recursion):

  >     if (c >= 1000)
  >     {
  >        r = int_name(c / 1000) + " thousand";
  >        c = c % 1000;
  >     }

## Walkthroughs

- Before entrusting a subprogram to a computer, it is a good idea to put it through a dry run or walkthourgh.
- Take out an index card and write down the name of the function you want to study.
- Write down the names of the function variables in a table, since you will update them as you walk through the code.

> `int_name(n = 416)`
> `c` | `r`
> `416` | `""`

- When your function calls another function, you can either start another card, or assume that it performs correctly.

> `int_name(n = 416)`
> `c` | `r`
> `416` | `""`
> `digit_name(n = 4)`
> `Returns "four"`

## Walkthroughs

- As the function progresses, update the variables by crossing out old values and writing down the new ones.

> `int_name(n = 416)`
> `c` | `r`
> `416` | `""`
> `16` | `"four hundred"`

> `int_name(n = 416)`
> `c` | `r`
> `416` | `""`
> `16` | `"four hundred"`
> `0` | `"four hundred sixteen"`

## Preconditions

- What should a function do when called with an inappropriate value (e.g. `sqrt(-1)`)?
  - A function can fail safely. For example, the `digit_name` function simply returns an empty string when it is called with an unexpected value.
  - A function can terminate. Many functions in the `cmath` library will terminate if given an illegal value.
- The most brutal method is to print a message and terminate the entire program.
- C++ has a very sophisticated mechanism called an exception.
- Whenever possible, it is desirable to avoid termination of the program (although that is hard).
- We will discuss using `assert()`.

## Preconditions (Syntax 5.6 : Assertions)

Syntax 5.6 : Assertions
    assert(expression);
Example: |
    assert(x >= 0);
Purpose: | If the expression is true, do nothing. If the expression is false, terminate the program, displaying the file name, line number, and expression.

## Preconditions

- To use `assert()` you must `#include<cassert>`.
- `assert()` is really a macro - a special instruction to the compiler that inserts complex code into the program.

  >     double future_value(double initial_balance, double p, int n)
  >     {
  >        assert(p >= 0);
  >        assert(n >= 0);

  >        return initial_balance * pow(1 + p / 100, n);
  >     }

- As a programmer, you must fully document any preconditions that the function must meet. That is, the legal values for function input.

  >     /**
  >        Computes the value of an investment with compound interest.
  >        @param initial_balance the initial value of the investment
  >        @param p the interest rate in percent; must be >= 0
  >        @param n the number of periods the investment is held; must be >= 0
  >        @return the balance after n periods
  >     */

- If a function call does not satisfy the preconditions, the function is free to do anything.
  - Function causes the program to terminate.
  - Return a "safe" default value.