\chapter{Functions: part 2}

\brenNote{This lecture is purposefully very short. I will run an
example stack machine with boxes etc which will chew up a fair bit of
time}

Remember the \pythoninline{print\_twice} function from the previous
lecture?  We are going to use it again, but we will change the
parameter name to something a bit more sensible.
\begin{python}
def print_twice(phrase):
    print phrase, phrase
\end{python}

\section{Variables and parameters are local}

When you create a \myidx{local variable} inside a function, it only
exists inside the function, and you cannot use it outside. For
example:
\begin{python}
def print_joined_twice(part1, part2):
    joined = part1 + part2
    print_twice(joined)
\end{python}

This function takes two arguments, concatenates them, and then prints
the result twice. We can call the function with two strings:

\begin{python}
>>> line1 = "Happy birthday, "
>>> line2 = "to you."
>>> print_joined_twice(line1, line2)
Happy birthday, to you. Happy birthday, to you.
\end{python}

When \pythoninline{print\_joined\_twice} terminates, the variable
\pythoninline{joined} is destroyed. If we try to print it, we get an
error:
\begin{python}
>>> print joined
NameError: name 'joined' is not defined
\end{python}

Parameters are also local. For example, outside the function
\pythoninline{print\_twice}, there is no such thing as
\pythoninline{phrase}. If you try to use it, Python will complain.

\section{Stack diagrams}

To keep track of which variables can be used where, it is sometimes
useful to draw a \myidx{stack diagram}. Like state diagrams, stack
diagrams show the value of each variable, but they also show the
function to which each variable belongs.
Each function is represented by a \myidx{frame}. A frame is a box
with the name of a function beside it and the parameters and variables
of the function inside it. The stack diagram for the previous example
looks like this:

\includegraphics[scale=1]{figures/stack-fig}

The order of the stack shows the flow of execution.
\pythoninline{print\_twice} was called by
\pythoninline{print\_joined\_twice}, and
\pythoninline{print\_joined\_twice} was called by
\pythoninline{\_\_main\_\_}, which is a special name for the topmost
function. When you create a variable outside of any function, it
belongs to \pythoninline{\_\_main\_\_}.  Each parameter refers to the
same value as its corresponding argument. So, \pythoninline{part1} has
the same value as \pythoninline{line1}, \pythoninline{part2} has the
same value as \pythoninline{line2}, and \pythoninline{phrase} has the
same value as \pythoninline{joined}.

If an error occurs during a function call, Python prints the name of
the function, and the name of the function that called it, and the
name of the function that called \emph{that}, all the way back to the
top most function.  To see how this works, we create a Python script
named \myurl{stacktrace.py} that looks like this:

\begin{python}
def print_twice(phrase):
    print phrase, phrase
    print joined

def print_joined_twice(part1, part2):
    joined = part1 + part2
    print_twice(joined)

line1 = "Happy birthday, "
line2 = "to you."
print_joined_twice(line1, line2)
\end{python}

We've added the statement, \pythoninline{print joined} inside the
\pythoninline{print\_twice} function, but \pythoninline{joined} is not
defined there. Running this script will produce an error message like
this:

\begin{pythonOutput}
Traceback (most recent call last):
  File "stack-example.py", line 11, in <module>
    print_joined_twice(line1, line2)
  File "stack-example.py", line 7, in print_joined_twice
    print_twice(joined)
  File "stack-example.py", line 3, in print_twice
    print joined
NameError: global name 'joined' is not defined
\end{pythonOutput}

This list of functions is called a \myidx{traceback}. It tells you
what program file the error occurred in, and what line, and what
functions were executing at the time. It also shows the line of code
that caused the error.
Notice the similarity between the traceback and the stack
diagram. It's not a coincidence. In fact, another common name for a
traceback is a \emph{stack trace}.

\section{Comments}

As programs get bigger and more complicated, they get more difficult
to read. Formal languages are dense, and it is often difficult to look
at a piece of code and figure out what it is doing, or why. For this
reason, it is a good idea to add notes to your programs to explain in
natural language what the program is doing. These notes are called
\myidx{comments}, and they are marked with the \# symbol:

\begin{python}
# compute the percentage of the hour that has elapsed
percentage = (minute * 100) / 60
\end{python}

In this case, the comment appears on a line by itself. You can also
put comments at the end of a line:

\begin{python}
percentage = (minute * 100) / 60     # caution: integer division
\end{python}

Everything from the \# to the end of the line is ignored---it has no
effect on the program. The message is intended for the programmer or
for future programmers who might use this code. In this case, it
reminds the reader about the ever-surprising behaviour of integer
division.

\section{Glossary}
 
\begin{description}

\item[local variable:]A variable defined inside a function. A local
  variable can only be used inside its function.
\item[stack diagram:]A graphical representation of a stack of
  functions, their variables, and the values to which they refer.
\item[frame:]A box in a stack diagram that represents a function
  call. It contains the local variables and parameters of the
  function.
\item[traceback:]A list of the functions that are executing, printed
  when a runtime error occurs. A traceback is also commonly referred to
  as a \emph{stack trace}, since it lists the functions in the order
  in which they are stored in the runtime stack.
\item[comment:]Information in a program that is meant for other
  programmers (or anyone reading the source code) and has no effect on
  the execution of the program.
 
\end{description}

\section{Laboratory exercises}

\begin{enumerate}


\item Create a script named \myurl{params.py} with the following
  contents:
\begin{python}
def print_param(x):
	print x

x = "Hello"
print_param("Goodbye")
print x
\end{python}
Record the output of the program here:
\begin{answerspace}


zend
\end{answerspace}

Explain the output in terms of what's happening to the variable
\pythoninline{x} and the parameter \pythoninline{x}:
\begin{answerspace}



zend
\end{answerspace}

\item Create a script called \myurl{changeparam.py} with the following
  contents:
\begin{python}
def change_param(x):
	x = "Goodbye"

x = "Hello"
change_param(x)
print x
\end{python}
Record the output of the program here:
\begin{answerspace}

zend
\end{answerspace}
Explain how the output comes about:

\begin{answerspace}





zend
\end{answerspace}

\item Place a comment character at the start of the last line (the one
  containing \pythoninline{print x}) in either of the last two
  programs and record what happens when you rerun it.
\begin{answerspace}


zend
\end{answerspace}

\item Try to figure out what the output of the program below will be.

\begin{python}
def print_all(first, second, third):
    print first, second, third

def print_reverse(first, second, third):
    print third, second, first

def print_add(first, second, third):
    print first + second + third

def print_add_reverse(first, second, third):
    print third + second + first

one = 'fish'
two = 'and'
three = 'chips'
print_all(one, two, three)
print_reverse(one, two, three)
print_add(one, two, three)
print_add_reverse(one, two, three)
print_all(1, 2, 3)
print_reverse(1, 2, 3)
print_add(1, 2, 3)
print_add_reverse(1, 2, 3)

\end{python}

Put your answer in the space below, and then type in and run the code
to check that you are right.

\begin{answerspace}



zend
\end{answerspace}


\item Type the following code into a file called \myurl{input\_fun.py}:
\begin{python}
print "Enter some text:"
text = raw_input()
print "You entered: " + text
print "Enter some text:"
text = raw_input()
print "You entered: " + text
print "Enter some text:"
text = raw_input()
print "You entered: " + text
\end{python}

Run the script to see what it does. Simplify the script by
encapsulating some of the code in a function.

\newpage
\item Create a script called \myurl{convert.py} which uses the
  function \pythoninline{raw\_input} to read a string from the
  keyboard. Attempt to convert the string to a float using
  \pythoninline{float(x)} and also to an integer using
  \pythoninline{int(x)}. Print out the resulting float and integer.
  Test the script with the following input:
\begin{pythonOutput}
10
103
1e12
0.000001
blah
\end{pythonOutput}
Explain the output produced:
\begin{answerspace}






zend
\end{answerspace}

\item Try to complete up to level nine on the game you played in the
  previous labs.
  % 8: multiple and repeated functions, 9: trickier function use
\end{enumerate}

\submitreminder
