Helper Functions and How They Work
Copyright (c) 2017 Kathi Fisler
We’ve been advising you to look closely at your code and find opportunities to create helper functions to "clean up your code". How does Pyret run a program that has helpers? What does "clean up" really mean? How do you decide when to use helper functions or define named expressions? This lecture steps back to review these questions, leveraging your having worked with these issues in lab and homework.
1 How Programs with Helpers Evaluate
Look at this complete file of the pen-cost programs. The file has functions to compute the cost of the pens, add shipping charges, compute the cost with shipping, and to give a bulk discount on large orders. (We haven’t yet seen the discount function in class).
Imagine that we enter pen-cost(10, "smile") at the prompt. How does Pyret evaluate this expression? It finds the definition of pen-cost, copies the function body, substitutes the arguments for the parameters, then evaluates the copied body.
Imagine that we enter add-shipping(pen-cost(10, "smile")) at the prompt. Pyret evaluates inside-out – it uses the substitution method to obtain the result of pen-cost(10, "smile"), which it then substitutes for order-amt in the body of add-shipping.
Some of you have asked about whether you can—
Watch the lecture capture to see this demonstrated step-by-step.
2 When is Code "Clean"?
Generally speaking, code is clean when the structure of the code reflects the high-level process/computation that the code performs. Look at the body of total-cost – the expression in the body summarizes the computation. We compute the pen cost then add the shipping. If you want the details of those steps, look at the bodies of the individual functions.
Programming Tip: When you get a programming problem, step back and ask what tasks or steps the computation requires. Plan to write a helper function for each of these tasks.
Named definitions inside functions arise for two purposes: either to name essential constants (character costs, pen prices, etc), or to name substeps of a task so you can easily find them later. The total-cost-discount2 function shows one other use: to save us writing out the exact same computation twice. If you find yourself repeating a computation verbatim, write it once and name the result.
If you find yourself repeating a computation almost verbatim, you can create a helper function instead. These helper functions arise not from high-level problem tasks, but from detail level repeated computations in code.
3 Practice: Binge Alert!
Let’s practice helpers and naming by working on the following problem.
A phone manufacturer needs to compute whether people are binging too much on apps in a 3-hour period. The will rate people’s usage based on the number of minutes spent on Facebook or Snapchat, as well as the number of times someone checked the news. People earn one usage point per minute on social media and 3 points per news check.
Based on the number of usage points, the app will give a severity rating of serious, moderate, mild, or normal. The conditions for each rating are as follows:
serious when usage is above 120 points
moderate when usage is above 60 points while at work or school
mild when usage is below 10 points
normal in all other cases
Develop a function binge-rating that takes the numbers of Facebook minutes, Snapchat minutes, and news checks, as well as the person’s location (work, school, vacation, etc) and returns a severity rating.
You can view the lecture capture to see how we developed this, and look at the final code file. Pay particular attention to how the functions and named definitions capture the structure of the computation.
4 Big Picture Take Aways
We started this course looking at how programs capture the structure of a computation or piece of complex data (i.e., images). Which expressions we use and how we nest them reflects the structure of the data or computation in a way that people can read off that structure.
Helper functions are the next step up in reflecting structure in code. We use helpers to name key tasks within our problem. Accounting for shipping costs and discounts are core steps in letting someone order items. We created a function for each task, tested each task separately from the others, then assembled the functions into our overall computation.
Key idea in CS: Use helpers to reflect the essential structure of the process you are performing in code. This aids readability of code and finding errors, since you can test each step separately.