The Recursive Book of Recursion: Ace the Coding Interview with Python and JavaScript
By Al Sweigart
()
About this ebook
Recursion has an intimidating reputation: it’s considered to be an advanced computer science topic frequently brought up in coding interviews. But there’s nothing magical about recursion.
The Recursive Book of Recursion uses Python and JavaScript examples to teach the basics of recursion, exposing the ways that it’s often poorly taught and clarifying the fundamental principles of all recursive algorithms. You’ll learn when to use recursive functions (and, most importantly, when not to use them), how to implement the classic recursive algorithms often brought up in job interviews, and how recursive techniques can help solve countless problems involving tree traversal, combinatorics, and other tricky topics.
This project-based guide contains complete, runnable programs to help you learn:
Al Sweigart has built a career explaining programming concepts in a fun, approachable manner. If you’ve shied away from learning recursion but want to add this technique to your programming toolkit, or if you’re racing to prepare for your next job interview, this book is for you.
Read more from Al Sweigart
Automate the Boring Stuff with Python, 2nd Edition: Practical Programming for Total Beginners Rating: 4 out of 5 stars4/5Invent Your Own Computer Games with Python, 4th Edition Rating: 4 out of 5 stars4/5Cracking Codes with Python: An Introduction to Building and Breaking Ciphers Rating: 0 out of 5 stars0 ratingsBeyond the Basic Stuff with Python: Best Practices for Writing Clean Code Rating: 0 out of 5 stars0 ratingsCoding with Minecraft: Build Taller, Farm Faster, Mine Deeper, and Automate the Boring Stuff Rating: 5 out of 5 stars5/5
Related to The Recursive Book of Recursion
Related ebooks
Ultimate Rust for Systems Programming Rating: 0 out of 5 stars0 ratingsMastering C: A Comprehensive Guide to Proficiency in The C Programming Language Rating: 0 out of 5 stars0 ratingsLinux Basics for SysAdmin: Learn core linux concepts and command-line skills to kickstart your system administration career Rating: 0 out of 5 stars0 ratingsPractical TTL Logic Gates: 74LS Integrated Circuits in Action Rating: 0 out of 5 stars0 ratingsMastering C# Concurrency Rating: 2 out of 5 stars2/5Becoming a Firefighter Rating: 0 out of 5 stars0 ratingsWorld On The Brink: G7 Vs. BRICS In The Quest For Dominance Rating: 0 out of 5 stars0 ratingsGraph Data Science with Python and Neo4j Rating: 0 out of 5 stars0 ratingsPython for Beginners Rating: 0 out of 5 stars0 ratingsNew York City Firefighter Exam Review Guide Rating: 0 out of 5 stars0 ratingsModern Web Development with Go: Build real-world, fast, efficient and scalable web server apps using Go programming language Rating: 0 out of 5 stars0 ratingsBeginning Unix Rating: 3 out of 5 stars3/5Tizen Cookbook Rating: 0 out of 5 stars0 ratingsHands-On Python for DevOps: Leverage Python's native libraries to streamline your workflow and save time with automation Rating: 0 out of 5 stars0 ratingsGuide to Captives and Alternative Risk Financing Rating: 0 out of 5 stars0 ratingsComputer Networking: Beginners Guide to Network Fundamentals, Protocols & Enterprise Network Infrastructure Rating: 0 out of 5 stars0 ratingsPython For Beginners Rating: 5 out of 5 stars5/5Visual Studio Code for Python Programmers Rating: 0 out of 5 stars0 ratingsCompTIA Network+ Practice Tests: Exam N10-009 Rating: 0 out of 5 stars0 ratingsPython Networking Essentials: Building Secure and Fast Networks Rating: 0 out of 5 stars0 ratingsThe Art of Docker: Streamline App Development and Deployment with Containerization (Computer Programming) Rating: 0 out of 5 stars0 ratingsProgramming Windows Workflow Foundation: Practical WF Techniques and Examples using XAML and C# Rating: 0 out of 5 stars0 ratingsThe IT Professional's Business and Communications Guide: A Real-World Approach to CompTIA A+ Soft Skills Rating: 0 out of 5 stars0 ratingsGitLab Guidebook: From Basics to Expert Proficiency Rating: 0 out of 5 stars0 ratingsVirtualization Essentials Rating: 0 out of 5 stars0 ratingsPattern-Oriented Software Architecture, Patterns for Resource Management Rating: 3 out of 5 stars3/5BlackBerry Planet: The Story of Research in Motion and the Little Device that Took the World by Storm Rating: 3 out of 5 stars3/5SignalR Realtime Application Cookbook Rating: 0 out of 5 stars0 ratingsWebRTC Cookbook Rating: 0 out of 5 stars0 ratings
Programming For You
SQL QuickStart Guide: The Simplified Beginner's Guide to Managing, Analyzing, and Manipulating Data With SQL Rating: 4 out of 5 stars4/5Linux: Learn in 24 Hours Rating: 5 out of 5 stars5/5Python: Learn Python in 24 Hours Rating: 4 out of 5 stars4/5Coding All-in-One For Dummies Rating: 4 out of 5 stars4/5Learn to Code. Get a Job. The Ultimate Guide to Learning and Getting Hired as a Developer. Rating: 5 out of 5 stars5/5Excel 101: A Beginner's & Intermediate's Guide for Mastering the Quintessence of Microsoft Excel (2010-2019 & 365) in no time! Rating: 0 out of 5 stars0 ratingsPython Programming : How to Code Python Fast In Just 24 Hours With 7 Simple Steps Rating: 4 out of 5 stars4/5Excel : The Ultimate Comprehensive Step-By-Step Guide to the Basics of Excel Programming: 1 Rating: 5 out of 5 stars5/5HTML in 30 Pages Rating: 5 out of 5 stars5/5SQL All-in-One For Dummies Rating: 3 out of 5 stars3/5Python Machine Learning By Example Rating: 4 out of 5 stars4/5Python: For Beginners A Crash Course Guide To Learn Python in 1 Week Rating: 4 out of 5 stars4/5Coding All-in-One For Dummies Rating: 0 out of 5 stars0 ratingsLearn SQL in 24 Hours Rating: 5 out of 5 stars5/5Python Data Structures and Algorithms Rating: 5 out of 5 stars5/5Learn PowerShell in a Month of Lunches, Fourth Edition: Covers Windows, Linux, and macOS Rating: 5 out of 5 stars5/5A Slackers Guide to Coding with Python: Ultimate Beginners Guide to Learning Python Quick Rating: 0 out of 5 stars0 ratingsCoding with JavaScript For Dummies Rating: 0 out of 5 stars0 ratings
Reviews for The Recursive Book of Recursion
0 ratings0 reviews
Book preview
The Recursive Book of Recursion - Al Sweigart
The Recursive Book of Recursion
Ace the Coding Interview with Python and JavaScript
by Al Sweigart
nsp_logo_black_rkTHE RECURSIVE BOOK OF RECURSION. Copyright © 2022 by Al Sweigart.
Some rights reserved. This work is licensed under the Creative Commons Attribution-NonCommercial-ShareAlike 3.0 United States License. To view a copy of this license, visit http://creativecommons.org/licenses/by-nc-sa/3.0/us or send a letter to Creative Commons, PO Box 1866, Mountain View, CA 94042, USA.
First printing
26 25 24 23 22 1 2 3 4 5
ISBN-13: 978-1-71850-202-4 (print)
ISBN-13: 978-1-71850-203-1 (ebook)
Publisher: William Pollock
Production Manager: Rachel Monaghan
Production Editor: Miles Bond
Developmental Editor: Frances Saux
Cover Illustrator: James L. Barry
Interior Design: Octopod Studios
Technical Reviewer: Sarah Kuchinsky
Copyeditor: Sharon Wilkey
Compositor: Maureen Forys, Happenstance Type-O-Rama
Proofreader: Audrey Doyle
For information on distribution, bulk sales, corporate sales, or translations, please contact No Starch Press, Inc. directly at [email protected] or:
No Starch Press, Inc.
245 8th Street, San Francisco, CA 94103
phone: 1.415.863.9900
www.nostarch.com
Library of Congress Cataloging-in-Publication Data
Library of Congress Control Number: 2022932456
No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names mentioned herein may be the trademarks of their respective owners. Rather than use a trademark symbol with every occurrence of a trademarked name, we are using the names only in an editorial fashion and to the benefit of the trademark owner, with no intention of infringement of the trademark.
The information in this book is distributed on an As Is
basis, without warranty. While every precaution has been taken in the preparation of this work, neither the author nor No Starch Press, Inc. shall have any liability to any person or entity with respect to any loss or damage caused or alleged to be caused directly or indirectly by the information contained in it.
To Jack, who held up a mirror in front of my mirror
About the Author
Al Sweigart is a software developer, fellow of the Python Software Foundation, and author of several programming books with No Starch Press, including the worldwide bestseller Automate the Boring Stuff with Python. His Creative Commons licensed works are available at https://www.inventwithpython.com.
About the Technical Reviewer
Sarah Kuchinsky, MS, is a corporate trainer and consultant. She uses Python for a variety of applications, including health systems modeling, game development, and task automation. Sarah is a co-founder of the North Bay Python conference, tutorials chair for PyCon US, and lead organizer for PyLadies Silicon Valley. She holds degrees in management science as well as in engineering and mathematics.
Foreword
When I was approached by Al to write the foreword to this book, I was pretty excited about the prospect. A book on recursion! Now, that’s something you just don’t see every day. Considered by many to be one of the more mysterious topics in programming, recursion is often discouraged. Oddly, this stands in stark contrast to its storied use in weird job interview questions.
However, there are all sorts of practical reasons to learn about recursion. Recursive thinking is very much a mindset about problem-solving. At its core, larger problems get broken into smaller problems. And sometimes along the way, hard problems are rewritten into equivalent but easier-to-solve simple problems. This sort of thinking can be a useful tool when applied to software design—even when recursion is not being used. Thus, it’s a worthy topic of study for programmers of all skill levels.
In my unbridled excitement to say more about recursion, I originally wrote this foreword in the form of a few short stories involving friends who’d applied recursive thinking in different ways but achieved a similar result. First there was the story of Ben, who learned about recursion, took it too far, and somehow managed to disappear off the face of the earth under mysterious circumstances after committing the following Python code into production:
result = [(lambda r: lambda n: 1 if n < 2 else r(r)(n-1) + r(r)(n-2))(
(lambda r: lambda n: 1 if n < 2 else r(r)(n-1) + r(r)(n-2)))(n)
for n in range(37)]
Then there was the story of Chelsea, who became so effective at real-world problem-solving that she was promptly fired! Oh, you wouldn’t believe how much all the fine editors at No Starch (bless their hearts) hated these stories. You can’t start a book by telling people stories like that. It’s just going to scare everyone away!
To be fair, they probably have a point. In fact, they even made me move a more reassuring paragraph about recursion from later in this foreword up to the second paragraph just so you wouldn’t first read about the stories of Ben and Chelsea and run away in a screaming horror to read a book about design patterns instead.
Clearly, writing the foreword to a book is serious business. So, regrettably, I’ll have to share the true stories of Ben and Chelsea with you another time. But, getting back to the book, it’s true that recursion is not a technique that gets applied to the vast majority of problems in day-to-day programming. As such, it often carries an aura of magic about it. This book hopes to dispel much of that. This is a good thing.
Finally, as you set off on your recursion journey, be prepared to have your brain bent in new directions. Not to worry—this is normal! However, it’s also important to stress that recursion is supposed to be a bit of fun. Well, at least a little bit. So, enjoy the ride!
—David Beazley
Author of Python Cookbook and Python Distilled
Teacher of aspiring problem solvers
https://www.dabeaz.com
Acknowledgments
It’s misleading to have only my name on the cover. I’d like to thank my publisher, Bill Pollock; my editor, Frances Saux; my technical reviewer, Sarah Kuchinsky; my production editor, Miles Bond; the production manager, Rachel Monaghan; and the rest of the staff at No Starch Press for their invaluable help.
Finally, I would like to thank my family, friends, and readers for all their suggestions and support.
Introduction
The programming technique of recursion can produce elegant code solutions. More often, however, it produces confused programmers. This doesn’t mean programmers can (or should) ignore recursion. Despite its reputation for being challenging, recursion is an important computer science topic and can yield keen insights into programming itself. At the very least, knowing recursion can help you nail a coding job interview.
If you’re a student with an interest in computer science, recursion is a necessary hurdle you’ll have to overcome to understand many popular algorithms. If you’re a programming bootcamp graduate or self-taught programmer who managed to bypass the more theoretical computer science topics, recursion problems are still sure to come up during whiteboard coding interviews. And if you’re an experienced software engineer who has never touched a recursive algorithm before, you might find recursion to be an embarrassing gap in your knowledge.
There’s no need to worry. Recursion isn’t as hard to understand as it is to teach. As I’ll explain in Chapter 1, I attribute the widespread misunderstanding of recursion to poor instruction rather than any inherent difficulty. And since recursive functions aren’t commonly used in day-to-day programming, many folks get along just fine without them.
But a certain conceptual beauty lies behind recursive algorithms that can aid your understanding of programming even if you don’t often apply them. Recursion has a visual beauty as well. The technique is behind the amazing mathematical art of fractals, the self-similar shapes shown in Figure 1.
Figure 1: These examples of fractals include a Sierpiński triangle (left), a Hilbert curve (center), and a Koch snowflake (right).
However, this book is not entirely in praise of recursion. I include some sharp criticisms of this technique. Recursion is overused in cases where a simpler solution exists. Recursive algorithms can be hard to understand, have worse performance, and are susceptible to crash-causing stack overflow errors. And a certain kind of programmer may use recursion not because it’s the right technique for a given problem, but simply because they feel smarter when they write code that other programmers struggle to understand. Computer scientist Dr. John Wilander once said, When you finish a PhD in computer science, they take you to a special room and explain that you must never use recursion in real life. Its only purpose is to make programming hard for undergrads.
So, whether you want to get an edge in coding interviews, you want to create beautiful mathematical art, or you stubbornly seek to finally understand the intriguing properties of this concept, this book will be your guide down the rabbit hole that is recursion (and the rabbit holes within that rabbit hole). Recursion is one of the computer science topics that separates the professionals from the beginners. By reading this book, you’ll master a great skill and learn its dark secret: recursion isn’t as complicated as people think it is.
Who Is This Book For?
This book is for those who are intimidated or intrigued by recursive algorithms. Recursion is one of those topics that seems like black magic to beginner programmers or freshman computer science students. Most recursion lessons are hard to follow and make the subject seem frustrating, even fearsome. For these readers, I hope this book’s direct explanations and ample examples can help make the topic finally click.
The only prerequisite for this book is basic programming experience with either the Python or JavaScript programming languages, which the chapters’ code examples use. The book’s programs have been stripped down to their essences; if you know how to call and create functions and the difference between global and local variables, you know enough to work through the programming examples.
About This Book
This book has 14 chapters:
Part I: Understanding Recursion
Chapter 1: What Is Recursion? Explains recursion and how it is the natural result of the way programming languages implement functions and function calls. This chapter also argues that recursion isn’t nearly the elegant, mystical concept many claim it is.
Chapter 2: Recursion vs. Iteration Dives into the differences (and many similarities) between recursive and iterative techniques.
Chapter 3: Classic Recursion Algorithms Covers famous recursive programs such as the Tower of Hanoi, the flood fill algorithm, and others.
Chapter 4: Backtracking and Tree Traversal Algorithms Discusses a problem for which recursion is particularly suited: traversing tree data structures, such as when solving mazes and navigating a directory.
Chapter 5: Divide-and-Conquer Algorithms Discusses how recursion is useful for splitting large problems into smaller subproblems and covers several common divide-and-conquer algorithms.
Chapter 6: Permutations and Combinations Covers recursive algorithms involving ordering and matching, as well as the common programming problems to which these techniques are applied.
Chapter 7: Memoization and Dynamic Programming Explains some simple tricks to improve code efficiency when applying recursion in the real world.
Chapter 8: Tail Call Optimization Covers tail call optimization, a common technique used to improve the performance of recursive algorithms, and how it works.
Chapter 9: Drawing Fractals Tours the intriguing art that can be programmatically produced by recursive algorithms. This chapter makes use of turtle graphics for generating its images.
Part II: Projects
Chapter 10: File Finder Covers a project that searches through the files on your computer according to custom search parameters you provide.
Chapter 11: Maze Generator Covers a project that automatically generates mazes of any size using the recursive backtracker algorithm.
Chapter 12: Sliding-Tile Solver Covers a project that solves sliding-tile puzzles, also called 15-puzzles.
Chapter 13: Fractal Art Maker Explores a project that can produce custom fractal art of your own design.
Chapter 14: Droste Maker Explores a project that produces recursive, picture-in-picture images using the Pillow image-manipulation module.
Hands-On, Experimental Computer Science
Reading about recursion won’t teach you how to implement it on its own. This book includes many recursive code examples in both the Python and JavaScript programming languages for you to experiment with. If you’re new to programming, you can read my book Automate the Boring Stuff with Python, 2nd edition (No Starch Press, 2019), or Python Crash Course, 2nd edition, by Eric Matthes (No Starch Press, 2019) for an introduction to both programming and the Python programming language.
I recommend stepping through these programs with a debugger. A debugger lets you execute programs one line at a time and inspect the state of the program along the way, allowing you to pinpoint where bugs occur. Chapter 11 of Automate the Boring Stuff with Python, 2nd edition, covers how to use the Python debugger and is free to read online at https://automatetheboringstuff.com/2e/chapter11.
The chapters in this book display the Python and JavaScript code examples together. The Python code is saved in a .py file, and the JavaScript code in an .html file (not a .js file). For example, take the following hello.py file:
print('Hello, world!')
And the following hello.html file:
document.write(Hello, world!
);
The two code listings act as a Rosetta stone, describing programs that produce the same results in two different languages.
Note
The
HTML tag in hello.html is a break return, also called a newline, which prevents all the output from appearing on a single line. Python’s print() function automatically adds break returns to the end of the text, while JavaScript’s document.write() function doesn’t.
I encourage you to manually copy these programs by using your keyboard, rather than simply copying and pasting their source code into a new file. This helps your muscle memory
of the programs and forces you to consider each line as you type it.
The .html files are technically not valid because they’re missing several necessary HTML tags, such as and , but your browser will still be able to display the output. These tags have been left out on purpose. The programs in this book are written for simplicity and readability, not to demonstrate web development best practices.
Installing Python
While every computer has a web browser that can view the .html files in this book, you must install Python separately if you wish to run the book’s Python code. You can download Python for Microsoft Windows, Apple macOS, and Ubuntu Linux for free from https://python.org/downloads. Be sure to download a version of Python 3 (such as 3.10) and not Python 2. Python 3 made a few backward-incompatible changes to the language, and the programs in this book may not run correctly, if at all, on Python 2.
Running IDLE and the Python Code Examples
You can use the IDLE editor that comes with Python to write your Python code or install a free editor, such as the Mu Editor from https://codewith.mu, PyCharm Community Edition from https://www.jetbrains.com/pycharm/download, or Microsoft Visual Studio Code from https://code.visualstudio.com/Download.
To open IDLE on Windows, open the Start menu in the lower-left corner of your screen, enter IDLE in the search box, and select IDLE (Python 3.10 64-bit).
On macOS, open the Finder window and click Applications▶Python 3.10, and then the IDLE icon.
On Ubuntu, select Applications▶Accessories▶Terminal and then enter IDLE 3. You may also be able to click Applications at the top of the screen, select Programming, and then click IDLE 3.
IDLE has two types of windows. The interactive shell window has the >>> prompt and is used for running Python instructions one at a time. This is useful when you want to experiment with bits of Python code. The file editor window is where you can enter full Python programs and save them as .py files. This is how you’ll enter the source code for the Python programs in this book. To open a new file editor window, click File▶New File. You can run the programs by clicking Run▶Run Module or pressing F5.
Running the JavaScript Code Examples in the Browser
Your computer’s web browser can run the JavaScript programs and display their output, but to write JavaScript code, you’ll need a text editor. A simple program like Notepad or TextMate will do, but you can also install text editors specifically for writing code, such as IDLE or Sublime Text from https://www.sublimetext.com.
After typing the code for your JavaScript programs, save the files as .html files, not .js files. Open them in a web browser to view the results. Any modern web browser works for this purpose.
Part I
UNDERSTANDING RECURSION
1
What Is Recursion?
Recursion has an intimidating reputation. It’s considered hard to understand, but at its core, it depends on only two things: function calls and stack data structures.
Most new programmers trace through what a program does by following the execution. It’s an easy way to read code: you just put your finger on the line of code at the top of the program and move down. Sometimes your finger will loop back; other times, it will jump into a function and later return. This makes it easy to visualize what a program does and in what order.
But to understand recursion, you need to become familiar with a less obvious data structure, called the call stack, that controls the program’s flow of execution. Most programming beginners don’t know about stacks, because programming tutorials often don’t even mention them when discussing function calls. Furthermore, the call stack that automatically manages function calls doesn’t appear anywhere in the source code.
It’s hard to understand something when you can’t see it and don’t know it exists! In this chapter, we’ll pull back the curtain to dispel the overblown notion that recursion is hard, and you’ll be able to appreciate the elegance underneath.
The Definition of Recursion
Before we begin, let’s get the clichéd recursion jokes out of the way, starting with this: To understand recursion, you must first understand recursion.
During the months I’ve spent writing this book, I can assure you that this joke gets funnier the more you hear it.
Another joke is that if you search Google for recursion, the results page asks if you mean recursion. Following the link, as shown in Figure 1-1, takes you to . . . the search results for recursion.
Screenshot of a Google search for the term “recursion.” Below the search bar is a banner that reads, “Did you mean: recursion.”Figure 1-1: The Google search results for recursion link to the Google search results for recursion.
Figure 1-2 shows a recursion joke from the webcomic xkcd.
A one-panel comic of someone reading the text “I’m so meta, even this acronym.”Figure 1-2: I’m So Meta, Even This Acronym (I.S. M.E.T.A.) (xkcd.com/917 by Randall Munroe)
Most jokes about the 2010 science fiction action movie Inception are recursion jokes. The film features characters having dreams within dreams within dreams.
And finally, what computer scientist could forget that monster from Greek mythology, the recursive centaur? As you can see in Figure 1-3, it is half horse, half recursive centaur.
Image of a statue with a horse’s body whose front legs and torso repeat, decreasing in size, in a spiral pattern.Figure 1-3: The recursive centaur. Image by Joseph Parker.
Based on these jokes, you might conclude that recursion is a sort of meta, self-referencing, dream-within-a-dream, infinite mirror-into-mirror sort of thing. Let’s establish a concrete definition: a recursive thing is something whose definition includes itself. That is, it has a self-referential definition.
The Sierpiński triangle in Figure 1-4 is defined as an equilateral triangle with an upside-down triangle in the middle that forms three new equilateral triangles, each of which contains a Sierpiński triangle. The definition of Sierpiński triangles includes Sierpiński triangles.
Graphic depicting three triangles. The first triangle has a smaller upside-down triangle in the center that divides the original into smaller triangles. The next triangle shows those three smaller outer triangles, each divided into still smaller triangles. The third triangle shows those smaller triangles further divided into triangles.Figure 1-4: Sierpiński triangles are fractals (recursive shapes) that include Sierpiński triangles.
In a programming context, a recursive function is a function that calls itself. Before we explore recursive functions, let’s take a step back and understand how regular functions work. Programmers tend to take function calls for granted, but even experienced programmers will find it worthwhile to review functions in the next section.
What Are Functions?
Functions can be described as mini-programs inside your program. They’re a feature of nearly every programming language. If you need to run identical instructions at three different places in a program, instead of copying and pasting the source code three times you can write the code in a function once and call the function three times. The beneficial result is a shorter and more readable program. The program is also easier to change: if you need to fix a bug or add features, you need to change your program in only one place instead of three.
All programming languages implement four features in their functions:
Functions have code that is run when the function is called.
Arguments (that is, values) are passed to the function when it’s called. This is the input to the function, and functions can have zero or more arguments.
Functions return a return value. This is the output of the function, though some programming languages allow functions not to return anything or to return null values like undefined or None.
The program remembers which line of code called the function and returns to it when the function finishes its execution.
Different programming languages might have additional features, or different options for how to call functions, but they all have these four general elements. You can visually see the first three of these elements because you write them in the source code, but how does a program keep track of where the execution should return to when the function returns?
To get a better sense of the problem, create a functionCalls.py program that has three functions: a(), which calls b(), which calls c():
Python
def a():
print('a() was called.')
b()
print('a() is returning.')
def b():
print('b() was called.')
c()
print('b() is returning.')
def c():
print('c() was called.')
print('c() is returning.')
a()
This code is equivalent to the following functionCalls.html program:
JavaScript
function a() {
document.write(a() was called.
);
b();
document.write(a() is returning.
);
}
function b() {
document.write(b() was called.
);
c();
document.write(b() is returning.
);
}
function c() {
document.write(c() was called.
);
document.write(c() is returning.
);
}
a();
When you run this code, the output looks like this:
a() was called.
b() was called.
c() was called.
c() is returning.
b() is returning.
a() is returning.
The output shows the start of functions a(), b(), and c(). Then, when the functions return, the output appears in reverse order: c(), b(), and then a(). Notice the pattern to the text output: each time a function returns, it remembers which line of code originally called it. When the c() function call ends, the program returns to the b() function and displays b() is returning. Then the b() function call ends, and the program returns to the a() function and displays a() is returning. Finally, the program returns to the original a() function call at the end of the program. In other words, function calls don’t send the execution of the program on a one-way trip.
But how does the program remember if it was a() or b() that called c()? This detail is handled by the program implicitly with a call stack. To understand how call stacks remember where the execution returns at the end of a function call, we need to first understand what a stack is.
What Are Stacks?
Earlier I mentioned the clichéd wisecrack, To understand recursion, you must first understand recursion.
But this is actually wrong: to really understand recursion, you must first understand stacks.
A stack is one of the simplest data structures in computer science. It stores multiple values like a list does—but unlike lists, it limits you to adding to or removing values from the top
of the stack only. For stacks implemented with lists or arrays, the top
is the last item, at the right end of the list or array. Adding values is called pushing values onto the stack, while removing values is called popping values off the stack.
Imagine that you’re engaged in a meandering conversation with someone. You’re talking about your friend Alice, which then reminds you of a story about your co-worker Bob, but for that story to make sense, you first have to explain something about your cousin Carol. You finish your story about Carol and go back to talking about Bob, and when you finish your story about Bob, you go back to talking about Alice. Then you are reminded about your brother David, so you tell a story about him. Eventually, you get around to finishing your original story about Alice.
Your conversation follows a stack-like structure, as in Figure 1-5. The conversation is stack-like because the current topic is always at the top of the stack.
A timeline that shows names stacked one on top of the other at various points in time. It begins with no names, then shows Alice, then Bob on top of Alice, then Carol on top of Bob on top of Alice, then Bob on top of Alice, then just Alice, then David on top of Alice, then Just Alice once more, then no names.Figure 1-5: Your meandering conversation stack
In our conversation stack, the new topics are added to the top of the stack and taken off as they are completed. The previous topics are remembered
underneath the current topic in the stack.
We can use Python lists as stacks if, to amend the list’s contents, we limit ourselves to the append() and pop() methods to perform pushing and popping. JavaScript arrays can also be used as stacks through their push() and pop() methods.
Note
Python uses the terms list and item, while JavaScript uses the terms array and element, but they are respectively identical for our purposes. In this book, I use the terms list and item for both languages.
For example, consider this cardStack.py program, which pushes and pops string values of playing cards to the end of a list named cardStack:
Python
cardStack = ❶ [] ❷
cardStack.append('5 of diamonds')
print(','.join(cardStack))
cardStack.append('3 of clubs')
print(','.join(cardStack))
cardStack.append('ace of hearts')
print(','.join(cardStack))
❸
cardStack.pop()
print(','.join(cardStack))
The following cardStack.html program contains the equivalent code in JavaScript:
JavaScript
let cardStack =
❶ []; ❷
cardStack.push(5 of diamonds
);
document.write(cardStack +
);
cardStack.push(3 of clubs
);
document.write(cardStack +
);
cardStack.push(ace of hearts
);
document.write(cardStack +
);
❸
cardStack.pop()
document.write(cardStack +
);
When you run this code, the output looks like this:
5 of diamonds
5 of diamonds,3 of clubs
5 of diamonds,3 of clubs,ace of hearts
5 of diamonds,3 of clubs
The stack starts off as empty ❶. Three strings representing cards are pushed onto the stack ❷. Then the stack is popped ❸, which removes the ace of hearts and leaves the three of clubs at the top of the stack again. The state of the cardStack stack is tracked in Figure 1-6, going from left to right.
Timeline showing playing cards stacked on top of each other at various points in time. Begins with no cards, then the five of diamonds, then the three of clubs on top of the five of diamonds, then the ace of hearts on top of the three of clubs, and finally the ace of hearts removed to reveal the three of clubs.Figure 1-6: The stack starts empty. Cards are then pushed onto and popped off the stack.
You can see only the topmost card in the card stack, or, in our program’s stacks, the topmost value. In the simplest stack implementations, you can’t see how many cards (or values) are in the stack. You can see only whether the stack is empty or not.
Stacks are a LIFO data structure, which stands for last in, first out, since the last value pushed onto the stack is the first value popped out of it. This behavior is similar to your web browser’s Back button. Your browser tab’s history functions like a stack that contains all the pages you’ve visited in the order that you visited them. The browser is always displaying the web page at the top
of the history’s stack.
Clicking a link pushes a new web page onto the history stack, while clicking the Back button pops the top web page off and reveals the one underneath.
What Is the Call Stack?
Programs use stacks too. The program’s call stack, also simply called the stack, is a stack of frame objects. Frame objects, also simply called frames, contain information about a single function call, including which line of code called the function, so the execution can move back there when the function returns.
Frame objects are created and pushed onto the stack when a function is called. When the function returns, that frame object is popped off the stack. If we call a function that calls a function that calls a function, the call stack will have three frame objects on the stack. When all these functions return, the call stack will have zero frame objects on the stack.
Programmers don’t have to write code dealing with frame objects, since the programming language handles them automatically. Different programming languages have different ways of implementing frame objects, but in general they contain the following:
The return address, or the spot in the program where the execution should move when the function returns
The arguments passed to the function call
A set of local variables created during the function call
For example, take a look at the following localVariables.py program, which has three functions, just as our previous functionCalls.py and functionCalls.html programs did:
Python
def a():
❶
spam = 'Ant'
❷
print('spam is ' + spam)
❸
b()
print('spam is ' + spam)
def b():
❹
spam = 'Bobcat'
print('spam is ' + spam)
❺
c()
print('spam is ' + spam)
def c():
❻
spam = 'Coyote'
print('spam is ' + spam)
❼ a()
This localVariables.html is the equivalent JavaScript program:
JavaScript
function a() {
❶
let