Before you keep reading...
Runestone Academy can only continue if we get support from individuals like you. As a student you are well aware of the high cost of textbooks. Our mission is to provide great books to you for free, but we ask that you consider a $10 donation, more if you can or less if $10 is a burden.
Before you keep reading...
Making great stuff takes time and $$. If you appreciate the book you are reading now and want to keep quality materials free for other students please consider a donation to Runestone Academy. We ask that you consider a $10 donation, but if you can give more thats great, if $10 is too much for your budget we would be happy with whatever you can afford as a show of support.
7.1. Functions and Composition¶
So far we have focused on writing procedures - problem solving recipes that do part of a job and return no answer. Now we will shift our attention to functions - problem solving recipes that are designed to calculate some value and return it to the code that calls the function so we can do more work with the result.
In the sample below, we can see the importance of returning results from functions so
that we can string together a number of steps. Line 3 calls the
input function to get
a string like
"4" from the user and store it as
Then on line 5 we use the
float function to turn that string into a numeric value
4.0 and store that in
sideA. We then use
math.pow to raise that value to the second
power and store the result as
aSquared gets used as part of the input
math.sqrt function which produces our final answer
sideC which gets passed to the
The fact that every function (other than
Note that just like with procedures, some functions like
input are standalone and are called
on their own. Other functions are part of a library or object and must be called with dot notation
7.1.1. Function Composition¶
We can more directly specify to use the result of calling one function as the input to another
function via functional composition. That is where we put one function call inside of another -
like how this version of the same program does
float(input("Enter length of side A")).
Like when doing math, we always do work inside of parentheses before worrying about the work
outside of them. In this case, that means we start with the
"Enter length of side A". It is
just a string, so there is nothing special to do with it other than use it as the argument to
input(). Then the
input function runs and does its job to get input from the user. It
returns a string with whatever the user typed. Recall that the mental model you should use forget
function calls is that they are replaced by the value they return. So
input("Enter length of side A") ends up just becoming something like
"4". That value
is what gets used as the argument for
sqrt(pow(sideA, 2) + pow(sideB, 2)) is evaluated, we have to start with the inner functions
and get answers for
pow(sideA, 2) and
pow(sideA, 2). Then we can add those answer to get
one number. That one number ends up being the argument for
sqrt which takes the square root of
it and returns the answer.
Writing code using functional composition in this style can make programs look shorter, but
it tends to make them harder to debug. In the first version of this program, we could add a
sqrt( pow(sideA, 2) + pow(sideB, 2) ), it can be hard to figure out what part is not
working as expected - the
+, or the