The Renegade Coder Code First. Ask Questions Later. Fri, 13 Sep 2019 14:10:35 +0000 en-US hourly 1 The Renegade Coder 32 32 127809749 I Started a Niche Site Fri, 20 Sep 2019 14:00:54 +0000

If you liked The Renegade Coder, you'll love Trill Trombone—a niche site by the same idiot!

The post I Started a Niche Site appeared first on The Renegade Coder.


After writing on this site for awhile, I thought it would be fun to try to take what I’ve learned to create a niche site. In particular, I decided to launch a site for one of my hobbies: playing trombone.

Table of Contents


Lately, I’ve been having struggling with figuring out who I want to be. After finding out that industry wasn’t for me, I tried to moving into academia. Now that I’m a year into that, I’m realizing that I don’t really like data visualization, so I’m trying to move into education.

Over time, I’ve realized that money would really alleviate this stress. After all, I wouldn’t have to worry about making any poor choices because I’d always have the money to do whatever I wanted. Unfortunately, I haven’t been able to earn much of anything on this site.

As fate would have it, I’ve been turned on to Income School which has a ton of YouTube videos on how to launch a niche site to earn money. Obviously, I broke a lot of those rules when I made this website, so I thought it would be fun to pivot into a new space with a new blog.


Now, you can’t exactly have big dreams without acting on them, so I decided to pull the trigger on a new domain: As a part of my hosting package, I was able to get this domain for free, and I even get to keep the contents in the same place as The Renegade Coder which is great.

Also, since I’m already used to working with WordPress, I decided to stick with that. However, I really made sure to pick a light (and free) theme this time around. Now, my new blog is blazing fast which should help me out in Google rankings.

In addition, I made sure to pick a topic that I could actually monetize. Unfortunately, teaching people to code isn’t all that lucrative—at least in terms of Amazon revenue. I don’t exactly write posts about products since almost everything I do is free.

With a site all about trombones, I have a lot I can monetize: trombones, slide lubricants, songbooks, mouthpieces, etc. And, I can write really focused articles about things I’m interested in.

At any rate, the site is up! By the time you’re reading this, I would expect there to be at least 10 articles, so that’s exciting. In fact, I’ve already written the following articles:

As you can see, a couple of these articles are extremely targeted. Hopefully, that means I’ll get extremely targeted traffic which means increased engagement and ultimately sales. In other words, I’ll be making some income through that site shortly—knock on wood!


As is often the case on this site, I like to share updates every now and again about what I’m working on related to this site. Typically, these articles are fairly short and include updates for projects like the Sample Programs repo. Of course, I felt website building was fairly related to what I do here, so I figured I’d share this story about my niche site.

As is customary at the end of my posts, I like to panhandle, so I don’t feel like my writing is just charity. In other words, become a patron, join the newsletter, write a comment, or buy some stuff from Amazon:

Of course, whatever you do, thanks for stopping by. I appreciate your time and attention.

The post I Started a Niche Site appeared first on The Renegade Coder.

]]> 0 18437
Data Science, the Good, the Bad, and the… Future Mon, 16 Sep 2019 14:00:45 +0000

For the first time in awhile, we have a bit of a community post. Check out this article on data science by Kirit Thadaka.

The post Data Science, the Good, the Bad, and the… Future appeared first on The Renegade Coder.


Hey! Jeremy here. Recently, someone from the editorial team for Kite, an AI autocomplete for Python, reached out to see if I would share some of their content. Since I thought the tool looked awesome, I figured I’d help them out. After some chatting, we decided on this data science article by Kirit Thadaka. Enjoy!

Table of Contents

What is Data Science?

How often do you think you’re touched by data science in some form or another? Finding your way to this article likely involved a whole bunch of data science (whooaa). To simplify things a bit, I’ll explain what data science means to me.

“Data Science is the art of applying scientific methods of analysis to any kind of data so that we can unlock important information.”

That’s a mouthful. If we unpack that, all data science really means is to answer questions by using math and science to go through data that’s too much for our brains to process.

Data Science covers…

  • Machine learning
  • Data visualization
  • Predictive analysis
  • Voice assistants

… and all the buzzwords we hear today, like artificial intelligence, deep learning, etc.

To finish my thought on data science being used to find this article, I’ll ask you to think of the steps you used to get here. For the sake of this explanation, let’s assume that most of you were online looking at pictures of kittens and puppies when you suddenly came across a fancy word related to data science and wanted to know what it was all about. You turned to Google hoping to find the meaning of it all, and you typed “What is *fill in your data science related buzzword*.”

You would have noticed that Google was kind enough to offer suggestions to refine your search terms – that’s predictive text generation. Once the search results came up, you would have noticed a box on the right that summarizes your search results – that’s Google’s knowledge graph. Using insights from SEO (Search Engine Optimization) I’m able to make sure my article reaches you easily, which is a good data science use case in and of itself. All of these are tiny ways that data science is involved in the things we do every day.

To be clear, going forward I’m going to use data science as an umbrella term that covers artificial intelligence, deep learning and anything else you might hear that’s relevant to data and science.

Positives: Astrophysics, Biology, and Sports

Data science made a huge positive impact on the way technology influences our lives. Some of these impacts have been nice and some have been otherwise. *looks at Facebook* But, technology can’t inherently be good or bad, technology is… technology. It’s the way we use it that has good or bad outcomes.

We recently had a breakthrough in astrophysics with the first ever picture of a black hole. This helps physicists confirm more than a century of purely theoretical work around black holes and the theory of relativity.

To capture this image, scientists used a telescope as big as the earth (Event Horizon Telescope or EHT) by combining data from an array of eight ground-based radio telescopes and making sense of it all to construct an image. Analyzing data and then visualizing that data – sounds like some data science right here.

A cool side note on this point: a standard Python library of functions for EHT Imaging was developed by Andrew Chael from Harvard to simulate and manipulate VLBI (Very-long-baseline interferometry) data helping the process of creating the black hole image.

Olivier Elemento at Cornell uses Big Data Analytics to help identify mutations in genomes that result in tumor cells spreading so that they can be killed earlier – this is a huge positive impact data science has on human life. You can read more about his incredible research here.

Python is used by researchers in his lab while testing statistical and machine learning models. Keras, NumPy, Scipy, and Scikit-learn are some top notch Python libraries for this.

If you’re a fan of the English Premier League, you’ll appreciate the example of Leicester City winning the title in the 2015-2016 season.

At the start of the season, bookmakers had the likelihood Leicester City winning the EPL at 10 times less than the odds of finding the Loch Ness monster. For a more detailed attempt at describing the significance of this story, read this.

Everyone wanted to know how Leicester was able to do this, and it turns out that data science played a big part! Thanks to their investment into analytics and technology, the club was able to measure players’ fitness levels and body condition while they were training to help prevent injuries, all while assessing best tactics to use in a game based on the players’ energy levels.

All training sessions had plans backed by real data about the players, and as a result Leicester City suffered the least amount of player injuries of all clubs that season.

Many top teams use data analytics to help with player performance, scouting talent, and understanding how to plan for certain opponents.

Here’s an example of Python being used to help with some football analysis. I certainly wish Chelsea F.C. would use some of these techniques to improve their woeful form and make my life as a fan better. You don’t need analytics to see that Kante is in the wrong position, and Jorginho shouldn’t be in that team and… Okay I’m digressing – back to the topic now!

Now that we’ve covered some of the amazing things data science has uncovered, I’m going to touch on some of the negatives as well – it’s important to critically think about technology and how it impacts us.

The amount that technology impacts our lives will undeniably increase with time, and we shouldn’t limit our understanding without being aware of the positive and negative implications it can have.

Some of the concerns I have around this ecosystem are data privacy (I’m sure we all have many examples that come to mind), biases in predictions and classifications, and the impact of personalization and advertising on society.

Negatives: Gender Bias and More

This paper published in NIPS talks about how to counter gender biases in word embeddings used frequently in data science.

For those who aren’t familiar with the term, word embeddings are a clever way of representing words so that neural networks and other computer algorithms can process them.

The data used to create Word2Vec (a model for word embeddings created by Google) has resulted in gender biases that show close relations between “men” and words like “computer scientist”, “architect”, “captain”, etc. while showing “women” to be closely related to “homemaker”, “nanny”, “nurse”, etc.

Here’s the Python code used by the researchers who published this paper. Python’s ease of use makes it a good choice for quickly going from idea to implementation.

It isn’t always easy to preempt biases like these from influencing our models. We may not even be aware that such biases exist in the data we collect.

It is imperative that an equal focus is placed on curating, verifying, cleaning, and to some extent de-biasing data.

I will concede that it isn’t always feasible to make all our datasets fair and unbiased. Lucky for us, there is some good research published that can help us understand our neural networks and other algorithms to the extent that we can uncover these latent biases.

When it comes to data science, always remember –

“Garbage in, garbage out.”

The data we train our algorithms with influences the results they produce. The results they produce are often seen by us and can have a lasting influence.

We must be aware of the impact social media and content suggestions have on us. Today, we’re entering a loop where we consume content that reinforces our ideas and puts people in information silos.

Research projects that fight disinformation and help people break out of the cycle of reinforcement are critical to our future. If you were trying to come up with a solution to this fake news problem, what would we need to do?

We would first need to come up with an accurate estimate of what constitutes “fake” news. This means comparing an article with reputable news sources, tracing the origins of a story, and verifying that the article’s publisher is a credible source.

You’d need to build models that tag information that hasn’t been corroborated by other sources. To do this accurately, one would need a ton of not “fake” news to train the model on. Once the model knows how to identify if something is true (to a tolerable degree of confidence), then the model can begin to flag news that’s “fake.”

Crowd sourced truth is also a great way to tackle this problem, letting the wisdom of the crowd determine what the “truth” is.

Blockchain technology fits in well here by allowing data to flow from people all over the world and arrive at consensus on some shared truth.

Python is the fabric that allows all these technologies and concepts to come together and build creative solutions.

Python, a Data Science Toolset

I’ve talked about data science, what it means, how it helps us, and how it may have negative impacts on us.

You’ve seen through a few examples how Python is a versatile tool that can be used across different domains, in industry and academia, and even by people without a degree in Computer Science.

Python is a tool that makes solving difficult problems a little bit easier. Whether you’re a social scientist, a financial analyst, a medical researcher, a teacher or anyone that needs to make sense of data, Python is one thing you need in your tool box.

Since Python is open source, anyone can contribute to the community by adding cool functionalities to the language in the form of Python libraries.

Data visualization libraries like Matplotlib and Seaborn are great for representing data in simple to understand ways. NumPy and Pandas are the best libraries around to manipulate data. Scipy is full on scientific methods for data analysis.

Whether you want to help fight climate change, analyze your favorite sports team or just learn more about data science, artificial intelligence, or your next favorite buzzword – you’ll find the task at hand much easier if you know some basic Python.

Here are some great Python libraries to equip yourself with:

  • NumPy
  • Pandas
  • Scikit-Learn
  • Keras
  • Matplotlib

I’ll illustrate an example of how easy it is to get started with data science using Python. Here’s a simple example of how you can use Scikit-Learn for some meaningful data analysis.

Python Example with Scikit-learn

This code is available at the Kite Blog github repository.

I’ve used one of Scikit-Learn’s datasets called Iris, which is a dataset that consists of 3 different types of irises’ (Setosa, Versicolour, and Virginica) petal and sepal length, stored in a 150×4 numpy.ndarray. The rows are the samples and the columns are: Sepal Length, Sepal Width, Petal Length, and Petal Width.

I’m going to run a simple linear regression to display the correlation between petal width length. The only libraries used here are scikit-learn (for the regression and data set) and matplotlib for the plotting.

from sklearn import datasets, linear_model
import matplotlib.pyplot as plt

iris = datasets.load_iris()

# Data and features are both numpy arrays
data =
features = iris.feature_names

Now, we’ll plot a linear regression between the length and width of the petals to see how they correlate.

# Create the regression model
regression = linear_model.LinearRegression()

# Reshape the Numpy arrays so that they are columnar
x_data = data[:, 2].reshape(-1, 1)
y_data = data[:, 3].reshape(-1, 1)

# Train the regression model to fit the data from iris (comparing the petal width), y_data)

# Display chart
plt.plot(x_data, regression.predict(x_data), color='black', linewidth=3)
plt.scatter(x_data, y_data)

Here’s a tutorial I created to learn NumPy, and here’s a notebook that shows how Keras can be used to easily create a neural network. Just this much will allow you to build some pretty cool models.

Concluding thoughts

Before I end, I’d like to share some of my own ideas of what I think the future of data science looks like.

I’m excited to see how concerns over personal data privacy shapes the evolution of data science. As a society, it’s imperative that we take these concerns seriously and have policies in place that prevent our data accumulating in the hands of commercial actors.

When I go for walks around San Francisco, I’m amazed at the number of cars I see with 500 cameras and sensors on them, all trying to capture as much information as they possibly can so that they can become self driving cars. All of this data is being collected, it’s being stored, and it’s being used. We are a part of that data.

As we come closer to a future where self driving cars become a bigger part of our life, do we want all of that data to be up in the cloud? Do we want data about the things we do inside our car available to Tesla, Cruise or Alphabet (Waymo)?

It’s definitely a good thing that these algorithms are being trained with as much data as possible. Why would we trust a car that hasn’t been trained enough? But that shouldn’t come at the cost of our privacy.

Instead of hoarding people’s personal data in “secure” cloud servers, data analysis will be done at the edge itself. This means that instead of personal data leaving the user’s device, it will remain on the device and the algorithm will run on each device.

Lots of development is happening in the field of Zero Knowledge Analytics which allows data to be analyzed without needing to see what that data is. Federated Learning allows people to contribute to the training of Neural Networks without their data to leaving their device.

The convergence of blockchain technology and data science will lead to some other exciting developments. By networking people and devices across the globe, the blockchain can provide an excellent platform for distributed computation, data sharing, and data verification. Instead of operating on information in silos, it can be shared and opened up to everyone. Golem is one example of this.

Hypernet is a project born out of Stanford to solve a big problem for scientists – how to get enough compute power to run computationally and data intensive simulations.

Instead of waiting for the only computer in the university with the bandwidth to solve the task and going through the process of getting permission to use it, Hypernet allows the user to leverage the blockchain and the large community of people with spare compute resources by pooling them together to provide the platform needed for intensive tasks.

Neural networks for a long time have felt like magic. They do a good job, but we’re not really sure why. They give us the right answer, but we can’t really tell how. We need to understand the algorithms that our future will be built on.

According to DARPA, the “third-wave” of AI will be dependent on artificial intelligence models being able to explain their decisions to us. I agree, we should not be at the mercy of the decisions made by AI.

I’m excited with what the future holds for us. Privacy, truth, fairness, and cooperation will be the pillars that the future of data science forms on.

This article originally appeared on Kite.

The post Data Science, the Good, the Bad, and the… Future appeared first on The Renegade Coder.

]]> 0 18413
How to Print on the Same Line in Python: Print and Write Fri, 13 Sep 2019 14:00:23 +0000

While Python is often convenient, sometimes it's not. For instance, it's unclear how you would print on the same line in Python. Luckily, we have the answer!

The post How to Print on the Same Line in Python: Print and Write appeared first on The Renegade Coder.


As someone who teaches a lot of beginner programming content, I occasionally stumble upon questions like “how do you print on the same line in Python?” Luckily, I have an answer to that!

In short, there are two main ways to print on the same line in Python. For Python 2, use the following print syntax: print "Williamson",. For Python 3, use the following print syntax: print("Providence", end=""). Otherwise, check out the remainder of the article for a backwards compatible solution.

Table of Contents

Problem Introduction

In many programming languages, printing on the same line is typically the default behavior. For instance, Java has two command line print functions:


As you can probably imagine, the default print function in Java is going to print without a newline character. In contrast, the println function is going to behave much like the print function in Python. Specifically, it’s going to print whatever string you provide to it followed by a newline character (i.e. \n).

Of course, if the print function in Python automatically prints a newline character with each call, then there’s no way to get the Java print behavior, right? Luckily, that’s not true! Otherwise, I wouldn’t have anything to write about out.


In order to print on the same line in Python, there are a few solutions. Unfortunately, not all of the solutions work in all versions of Python, so I’ve provided three solutions: one for Python 2, another for Python 3, and a final solution which works for both.

Print on the Same Line The Old Way

When I was searching for solutions to this problem, I found a lot of material on Python 2 which is quickly phasing out (I hope). That said, I felt this solution would be helpful to anyone still rocking it.

At any rate, when you print something in Python 2, the syntax is the same as Python 3, but you leave out the parentheses:

print "Live PD"

Of course, in both cases, the default behavior is to print with a newline. As a result, we’ll need to add a clever bit of syntax—a comma:

print "Live PD",

Now, the print function should exclude the newline. However, this solution will add an extra space to the end of the string. Also, you may notice that this solution does not print immediately. If that happens, you can make a call to sys.stdout.flush().

Print on the Same Line with the Write Function

Fortunately, we can bridge the gap between Python 2 and 3 using a function out of the sys library: write. This functions works just like the print function, but there’s no implicit newline:

import sys
sys.stdout.write("Breaking Bad")

Again, since there is no newline, you may need to flush the buffer to see any results:

import sys
sys.stdout.write("Breaking Bad")

In either case, this solution will get the job done in both versions of Python.

Print on the Same Line the New Way

In Python 3, print is a standard function. As a result, it has additional opportunities for parameters. In particular, there is a keyword argument called end which defaults to some newline character. You can easily change it as follows:

print("Mob Psycho 100", end="")

And, that’s it! Instead of the string ending in a newline, it will end in an empty string. Of course, this solution comes with the same caveat as the other previous two solutions: you may need to flush the buffer.


As always, I like to take a look at all the solutions from the point of view of performance. To start, I usually store each solution in a string. To avoid excessive printing during the test, I’ve chosen to write empty strings:

import sys

write_solution = """

print_solution = """
print("", end="")

Unfortunately, I was unable to test the Python 2 solution on my system, so feel free to share your results in the comments. At any rate, I like to use the timeit library for a quick and dirty performance test:

>>> import timeit
>>> min(timeit.repeat(stmt=write_solution, setup=setup, repeat=10))
>>> min(timeit.repeat(stmt=print_solution, setup=setup, repeat=10))

Clearly, the print function has quite a bit of overhead. In other words, if performance matters, go the write route. Otherwise, print works great!

A Little Recap

Well, that’s it for this one. Check out the code block below for a list of all the solutions:

# Python 2 only
print "Live PD",

# Backwards compatible (also fastest)
import sys
sys.stdout.write("Breaking Bad")

# Python 3 only
print("Mob Psycho 100", end="")

As always, if you know any other ways to print on the same line in Python, let us know in the comments. In the meantime, why not grow your Python knowledge with the following articles:

If you liked this article or any of the ones I listed, consider sticking around long term by becoming a member of the community or hopping on the mailing list.

While you’re here, why not take advantage of some these Python books:

Otherwise, I appreciate the support. Thanks for stopping by!

The post How to Print on the Same Line in Python: Print and Write appeared first on The Renegade Coder.

]]> 0 18345
The Lisp Programming Language: Interpreter Design Mon, 09 Sep 2019 14:00:42 +0000

At this point, it's probably no surprise that I'm studying Lisp and interpreter design for my qualifying exam. Let's study together!

The post The Lisp Programming Language: Interpreter Design appeared first on The Renegade Coder.


Perhaps to no one’s surprise, I’m writing yet another article on content that I’m studying for my qualifying exam. Apparently, I figure that I can point to this when I inevitably fail my exam, but I digress. Let’s talk about the Lisp programming language and how to design an interpreter for it.

Table of Contents

Lisp Overview

Honestly, I hadn’t touched any functional programming until I started playing around with languages like Haskell and Scheme in my Sample Programs in repo. Of course, eventually I learned about Lisp as a part of a programming languages course at The Ohio State University. Naturally, I have an exam on this very subject in just over a week, so let’s dig in.

First off, Lisp is one of the oldest programming languages—second to FORTRAN, I believe. Of course, Lisp differs from FORTRAN quite a bit in that it’s a functional programming language. In other words, there’s no notion of state or side-effects. Instead, computations are expressed through functions and expressions rather than statements.

In this article, we’ll talk about a fairly limited form of Lisp which only has a handful of builtin functions. As a result, don’t expect to be able to pass any of the code we discuss directly into a Scheme interpreter or anything like that.

Lisp S-Expressions

In order to grasp Lisp, it’s important to understand its design. Specifically, everything in Lisp is a symbolic expression or s-expression which is a text-based way of expressing a binary tree. In other words, instead of drawing out a binary tree, we can write one using parentheses and dots:

Symbolic Expressions Diagram

Of course, the smallest possible s-expression is called an atom. As the name implies, an atom is an indivisible programming element like a number or a function name. In this case, atoms are what get stored in the leaves of the binary tree.

In Lisp, these s-expressions are all we need to understand to be able to grasp the language. After all, everything else is built on top of them.

Lisp Syntax

Given what we know about s-expressions, let’s take a look at a simple Lisp grammar as provided in the slides for the CSE 6431 course at OSU:

<atom> ::= <numeric atom> 
    | <literal atom>
<numeric atom> ::= <numeral> 
    | -<numeral> 
    | +<numeral>
<numeral> ::= <digit> 
    | <numeral><digit>
<literal atom> ::= <letter> 
    | <literal atom><letter>
    | <literal atom><digit>
<letter> ::= a 
    | A 
    | b 
    | B 
    | … 
    | z 
    | Z
<digit> ::= 0 
    | 1 
    | 2 
    | … 
    | 9
<S-exp> ::= atom 
    | (<S-exp> . <S-exp>)

In its simple form, Lisp is composed of s-expressions which can either be standalone atoms or nested s-expressions of the form (<s-exp> . <s-exp>).

From there, we define two productions for atoms. On one hand, they can be integers of arbitrary size or literals which are essentially strings.

All that said, most forms of Lisp include yet another s-expression production called the list:

list ::= (<items>)
    | ()
items ::= <S-exp>
    | <S-exp> <items>

In other words, a list would look like a space-separated collection of s-expressions. Of course, as a binary tree, a list looks as follows:

Lisp Semantics

At this point, we’ve looked quite a bit at what Lisp looks like, but we haven’t talked a lot about how Lisp actually works. For example, the following code snippet is perfectly valid Lisp syntax, but what does it do?

(cons (cdr ′(11 . 6)) (car ′(4 . 5))) 

In this case, we’ll generate a new s-expression that looks like (6 . 4), but how would we know that? As it turns out, Lisp has a ton of builtin functionality.


First, we should talk about how we can build up our binary trees using a function called cons. cons, short for construct, creates an s-expression from two s-expressions:

(cons 4 7)

In this example, cons is supplied two atoms: 4 and 7. As a result, cons returns an s-expression of the form (4 . 7).

Naturally, we can nest cons calls to create more interesting s-expressions:

(cons (cons 1 2) 3)

In this case, the inner cons would construct (1 . 2) which would then be combined with 3 to form ((1 . 2) . 3).


First, we should talk about the two s-expression traversal functions: car and cdr. I call them traversal functions because they allow us to access nodes in our binary trees. For example, if we had the s-expression (3 . 7), we could return the left s-expression, 3, using car and the right s-expression, 7, using cdr.

Interestingly enough, car and cdr are often extend to provide even deeper nesting functionality. For example, cadr would grab the right s-expression using cdr then grab the left s-expression of the child using car.

In situations where we have atoms, car and cdr and their extended forms have undefined behavior. In other words, they should return an error.


In addition to the traversal functions, there are a handful of unary functions which can be used to test s-expressions for various properties.

One of those unary functions is called atom, and like the other two unary functions, it accepts one s-expression as input (i.e. (atom 5)) If the s-expression is an atom, the function returns T. Otherwise, it returns NIL.

Naturally, both int and null perform similarly. In particular, int returns T if the s-expression is an integer and NIL otherwise. Likewise, null returns T if the s-expression is NIL and NIL otherwise.

As you can probably imagine, these three functions are useful when writing custom functions. For example, if we want to write a function which can find the smallest element in a list, a null check would be a good place to start.


Like most programming languages, there has to be some way to perform arithmetic. Of course, in a purely functional language, operators are replaced by functions. For instance, addition might look as follows:

(plus 2 7)

In total, there are five arithmetic functions in Lisp—plus, minus, times, quotient, and remainder—and they correspond to addition, subtraction, multiplication, division, and remainder, respectively.


In addition to the arithmetic functions, there are also relational functions similar to less than, greater than, and equals in other languages. For example, the check if two values are equal, we would use the EQ function:

(eq 7 2)

In this case, the expression evaluates to false because 7 is not equal to 2. Naturally, all three of these functions work similarly.


One of the interesting features of Lisp is how everything gets evaluated in the interpreter. Each time the interpreter encounters an expression, it attempts to evaluate it. As a result, there are expressions which seem valid to us but are not to the interpreter. For example, the following might seem fine:

(atom (2 3 5))

Unfortunately, this will crash because (2 3 5) has to be evaluated. Naturally, it has no semantic meaning, so the interpreter tries to treat it like a function. Since 2 isn’t a function name, the interpreter crashes with an error:

2 is not a function name; try using a symbol instead

Instead, we can use the quote function to say to the interpreter: “return this value without evaluating it.”

(atom (quote (2 3 5))

As you can imagine, quote can really blow up a code base, so most versions of Lisp have some form of syntactic sugar as follows:

(atom '(2 3 5))

Now, that’s slick! And of course, this expression now returns NIL.


Another interesting feature of Lisp is the ability to build up control flow similar to a switch statement:

    (b1 e1)
    (b2 e2)
    (bn en)

Here, each boolean expression is evaluated from b1 to bn until one of the expressions returns T. The passing expression then executes its corresponding expression. For example, if b2 evaluates to T then e2 is evaluated.

Naturally, we can use this syntax for more interesting logic which we’ll get to in the next section.


Finally, there’s a syntax for creating our own functions called defun. In general, the syntax is as follows:

(defun f (x y) z)

Here, the function name is denoted by f, and the function parameters are denoted by the list containing x and y. Ultimately, the function body is denoted by z.

Based on all the functions we’ve covered up to this point, Lisp functions must be recursive, right? After all, there are no loops in Lisp, so any sort of repetition must be accomplished exclusively through function calls. For example, if we wanted to write a function to search a list for a value, it might look as follows:

(defun find (val list)
        ((null list) nil )
        (T (cond
            ((eq val (car list)) T )
            (T (find val (cdr list)))))))

Honestly, I don’t know what the best indentation would be here, but this function gets the job done. It works by first checking if the input list is null. If it is, then we’re done. Otherwise, we check to see if the first value in the list is what we want. If it is, we return true. Otherwise, we run a recursive call on the remainder of the list.

If we want to use our new find function, we call it as follows:

 (find 4 `(3 7 2 4))

Since 4 is in this list, we return T as expected.

At this point, we’ve covered just about everything about the syntax and semantics of Lisp. Now, let’s get into the interpreter design.

Lisp Interpreter Design

As it turns out, we can actually use Lisp to define our Lisp interpreter—aka bootstrapping. In particular, we’ll be looking at the interpeter from the point of view of the top-level eval function.


As the name states on the tin, eval evaluates a Lisp s-expression. However, in addition to the s-expression, a eval function requires a bit of context in the form of two lists: the association list (a-list) and the function definition list (d-list).

Specifically, the a-list stores all parameter bindings within the current scope in the following form:

((parameter1 . binding1) (parameter2 . binding2) ...)

Meanwhile, the d-list stores all function definitions in the following form:

((function_name1 (param_list1 . body1)) (function_name2 (param_list2 , body2) ...)

Unlike like the a-list, the d-list is global and consequently one of the few parts of Lisp that introduces side-effects.

At any rate, these two lists are then passed to eval which has the following body:

eval(exp, a_list, d_list) =
    [atom[exp] -> 
        [eq[exp, T] -> T |
         eq[exp, NIL] -> NIL |
         int[exp] -> exp |
         bound[exp, a_list] -> getval[exp, a_list] |
         T -> ERROR!]
    T -> 
        [eq[car[exp], quote] -> cadr[exp] |
         eq[car[exp], cond] -> evcon[cdr[exp], a_list, d_list] |
         eq[car[exp], defun] -> add to d_list |
         T -> apply[car[exp], evlist[cdr[exp], a_list, d_list], a_list, d_list]]]

Now, that’s surprisingly simply. In fact, this alone is the interpreter. Obviously, there are a few undefined functions here and even some pseudocode, but this is incredibly elegant.

In the first of eval, we deal with atoms only. In particular, we handle the three main atoms—T, NIL, and integers—as well as any symbol bindings such as variables. If we find a symbol binding with bound, we return that binding using getval.

In the second half of eval, we deal with everything else. First, we check if the left element of our s-expression is quote, cond, or defun, and then we apply whatever makes sense for those three special functions. Otherwise, we attempt to apply whatever symbol we see.

In the next few sections, we break down some of these undefined functions.


Whenever we have a set of conditions, we use a special function called evcon to evaluate them:

evcon[cond_list, a_list, d_list] =
    [null[cond_list] -> ERROR! |
     eval[caar[cond_list], a_list, d_list] -> eval[cadar[cond_list], a_list, d_list] |
     T -> evcon[cdr[cond_list], a_list, d_list]

As expected, evaluating a set of conditions is pretty simply. If there are no conditions, we throw an error. If the current condition evaluates to T, we evaluate its expression. Otherwise, we grab the next condition, and recursively call evcon on it.


Like evcon, evlist is also a pretty simple helper function. It’s main role is to evaluate each expression in a list, and return a new list with all of the expressions evaluated:

evlist[arg_list, a, d] =
    [null[arg_list] -> NIL |
     T -> cons[eval[car[arg_list], a_list, d_list], evlist[cdr[arg_list], a_list, d_list]]]

With evlist, we iterate over the list while evaluating each expression. Each result is then combined with the result of a recursive call on the remainder of the list. The result should be a list of evaluated s-expressions.


Finally, we bring the interpreter home with an implementation of the apply function:

apply[fname, arg_list, a_list, d_list] =
    [atom[fname] ->
        [eq[fname, car] -> caar[list] |
         eq[fname, cdr] -> cdar[list] |
         eq[fname, cons] -> cons[car[list], cadr[list]] |
         eq[fname, atom] -> atom[car[list]] |
         eq[fname, eq] -> eq[car[list], cadr[list]] |
         int, null, plus, minus, less, etc. |
         T -> eval[cdr[getval[fname, d_list]], 
                  addpairs[car[getval[fname, d_list]], list, a_list], 
    ] |
    T -> ERROR! ]

Naturally, apply is a bit bigger than all the other functions because we have to perform manual checks for each of our builtin functions: car, cons, plus, null, etc.

Of course, the most interesting part of the apply function is the last case which covers user-defined functions. In that case, we bind the formal parameters to the function arguments using addpairs and place the results in the a-list. Then, we evaluate the function body with the new bindings in the a-list.

And, that’s it! That’s the entire Lisp interpreter written in mathematical notation for Lisp. Overall, the interpreter looks like its about 30 or 40 lines of code, but my buggy Java implementation is much larger.

Want to Learn More?

Naturally, there’s a lot more I can cover in terms of Lisp, but I think that’s enough for today. After all, I have a lot more studying to do.

If you liked this article and you’d love to get content like this sent directly to your inbox, subscribe to The Renegade Coder newsletter. As always, you’re welcome support the site directly through Patreon as many people already do. Your support goes a long way to keeping educational content like this free to the public.

If you’re looking to pick up any Computer Science books, might I suggest a few:

As always, I try to find good resources for my readers, but you’re welcome share some of your own. Alternatively, you can always stick around. Here are few functional programming articles:

At any rate, thanks again for your support. If this is your first time reading my work, let me know what you think of it in the comments!

The post The Lisp Programming Language: Interpreter Design appeared first on The Renegade Coder.

]]> 0 18079
How to Format a String in Python: Interpolation, Concatenation, and More Fri, 06 Sep 2019 14:00:11 +0000

In this article, we learn how to format a string in Python using a handful of techniques including concatenation and interpolation.

The post How to Format a String in Python: Interpolation, Concatenation, and More appeared first on The Renegade Coder.


It’s been awhile since I’ve written one of these “how to” articles, but I’m back at it. This time, I want to talk about string formatting using techniques like interpolation and concatenation. In other words, it’s time to finally learn how to format a string in Python

Table of Contents

Problem Introduction

Whether we’re trying to prompt a user or output a nice error message, string formatting can always be challenging. After all, the syntax varies from language to language which can feel like learning a metalanguage. For instance, in languages like Java and C, string formatting relies on understanding concepts like variable arguments and format specifiers:

printf("Hi, %s", Jeremy);  // Prints "Hi, Jeremy"

Of course, string formatting gets more complicated as we introduce different data types. For example, numbers have their own set of specifiers: %d, %f, etc. And, we can even specify how the numbers look in terms of padding and truncation.

That said, I don’t you’re here to learn string formatting in C, so how do we accomplish the same thing in Python? In this article, we’ll take a look at several methods—some silly—just to illustrate how many ways there are to solve this problem.

To get started, we’ll need a universal example which contains a few pitfalls like mixing numbers and strings. The following code snippet will serve as our base for the remainder of the article:

name = "Jeremy"
age = 25

Using these variables, we’ll want to construct the following sentence:

print("My name is Jeremy, and I am 25 years old.")

Of course, feel free to swap the name and age with your name and age!


As it turns out, there are quite a few ways to format a string. We’ll start from a few direct approaches, then we’ll move into some the for elegant solutions.

Format a String Using Concatenation

If you’re like me, concatenation is something you learned when you first started to code. As a result, concatenation can seem like a quick shortcut to string formatting:

print("My name is " + name + ", and I am " + age + " years old.")

Unfortunately, a solution like this won’t work. If you tried to run this code, you’ll get a nasty error that looks something like this:

Traceback (most recent call last):
File “”, line 1, in
“My name is ” + name + “, and I am ” + age + ” years old.”
TypeError: can only concatenate str (not “int”) to str

Hopefully, the TypeError gives you the hint that the interpreter doesn’t like it when we try to concatenate a string with an integer. In other words, we need to cast the age variable to a string:

print("My name is " + name + ", and I am " + str(age) + " years old.")

And, that’s it! For small strings, this is probably fine, but it’s not super readable. Also, it’s really easy to forget spaces on either side of the variables we’re concatenating. Luckily, there are other ways to build a string.

Format a String Using Multiple Print Statements

Who needs concatenation when we can just call print a bunch of times?

print("My name is ", end="")
print(name, end="")
print(", and I am ", end="")
print(age, end="")
print(" years old.")

Now, I know what you’re thinking; yes, this only works in Python 3+. Oh, and this is a totally ridiculous solution, but it demonstrates something important: there are a lot of ways to solve the same problem.

In this case, we’ve taken the print function and leveraged one of its default arguments (end) to remove the newline behavior. That way, we could string together some text without concatenation.

Again, this is definitely hard to read, and I wouldn’t even advise it for small strings. That said, it does eliminate a type cast. Unfortunately, it introduces a lot of duplicate code.

Format a String Using the Join Function

Continuing our quest for the most ridiculous way of formatting a string, I bring you the join function. If you’re not familiar with this function, it’s basically a more efficient way to concatenate strings. In addition, it allows us to provide a separator to place between our concatenated strings. Of course, we won’t be needing that:

print(''.join(["My name is ", name, ", and I am ", str(age), " years old"]))

Here, we’ve called the join method on an empty separator string. As an argument, we’ve passed it a list of strings. Naturally, join will combine this list of strings into a single string without any separators.

Oddly enough, I sort of like this solution because it’s surprisingly readable. Unfortunately, there are a few drawbacks. For instance, we have to convert all our variables to strings manually. In addition, this line is already pretty long. Though, I suppose we could break everything out onto its own line.

At any rate, with these three out of the way, we can finally start getting to some more reasonable solutions.

Format a String Using the % Operator

Now, we’re starting to get into the actual string formatting techniques. As it turns out, Python has its own set of formatting tools similar to printf from C:

print("My name is %s, and I am %d years old." % (name, age))

Here, we’ve constructed a new string with %s replaced by name and %d replaced by age.

In addition to knowing the format specifiers, we’ll want to learn the syntax. In particular, our template string is following by the modulo operator. Of course, in this context, we can call it the string formatting or interpolation operator.

Then, we create a tuple of values that we want to place in our string. Be very careful to ensure the order of these values. If they are out of order, the resulting string may be incorrect, or the program may crash altogether.

With this method, we get a much cleaner solution. Of course, there are pitfalls here, but they mostly have to do with how the values are mapped to the string. For example, we have to pay attention to how we order our arguments, and we need to know our format specifiers.

Speaking of format specifiers, what if we want to print out an object directly? Fortunately, we have better solutions ahead.

Format a String Using the Format Function

Instead of using a fancy overloaded operator, we can make our code even more readable by using the format function for strings:

print("My name is {}, and I am {} years old".format(name, age))

Previously, we would have had to use format specifiers to get the behavior we wanted, but now we can just use braces. In other words, we’ve eliminated a problem from the previous solution.

From what I understand, this method leverages the __format__ method for objects, so we can pass just about anything to this method without issue. There goes yet another problem! Of course, if the class doesn’t have __str__ or __repr__ overridden, then the object will not print nicely. That said, I still count that as a win over the previous solution.

As it turns out, we can eliminate our ordering issue from the previous solution as well. All we have to do is provide keyword arguments:

print("My name is {n}, and I am {a} years old".format(a=age, n=name))

In this example, we named the age keyword a and the name keyword n. That way, we could place the keywords inside their respective braces. To further drive home the point, we can even reorder the arguments without issue. Now that’s pretty cool!

Of course, I should warn you that this solution may pose a security threat to your application depending on how you’re using it. If you’re writing your own format strings, there shouldn’t be any issues. However, if your accepting format strings from your users, you might want to be careful.

Format a String Using f-Strings

Another way to perform string interpolation is using Python’s latest f-String feature (Python 3.6+). With this feature, all we need to do is prefix a string with the letter f and insert braces just like before. However, this time, we can insert the name of our variables directly:

print(f"My name is {name}, and I am {age} years old")

Now, that is incredibly elegant. No longer do we have to worry about:

  • Mapping arguments to format specifiers
  • Using format specifiers correctly
  • Remembering obscure syntax

Instead, we prepend and f and insert our variables. That’s it! Now, I don’t know if there are any sort security vulnerabilities with this solution, but as far as I can tell, there’s no way to apply the f to an input string.

At any rate, that’s all I have for string formatting solutions. Now, let’s start to compare the performance of these solutions.


As always, I like to setup on all of our solutions in strings first:

setup = """
name = "Jeremy"
age = 25

concatenation = """
"My name is " + name + ", and I am " + str(age) + " years old."

string_join = """
''.join(["My name is ", name, ", and I am ", str(age), " years old"])

modulus = """
"My name is %s, and I am %d years old." % (name, age)

format_ordered = """
"My name is {}, and I am {} years old".format(name, age)

format_named = """
"My name is {n}, and I am {a} years old".format(a=age, n=name)

f_string = """
f"My name is {name}, and I am {age} years old"

For my sanity, I had to remove the print statements. As a result, I wasn’t able to test the print solution. That said, feel free to try your hand at it. I ran into some issues with the output string slowing down the test, and I even tried rerouting stdout to deal with it. It was a nightmare to say the least.

At any rate, it’s just a matter of calling our timeit commands now:

>>> import timeit
>>> min(timeit.repeat(stmt=concatenation, setup=setup, repeat=10))
>>> min(timeit.repeat(stmt=string_join, setup=setup, repeat=10))
>>> min(timeit.repeat(stmt=modulus, setup=setup, repeat=10))
>>> min(timeit.repeat(stmt=format_ordered, setup=setup, repeat=10))
>>> min(timeit.repeat(stmt=format_named, setup=setup, repeat=10))
>>> min(timeit.repeat(stmt=f_string, setup=setup, repeat=10))

As is often the case with these new features in Python, they are incredibly optimized. As a matter of fact, the only solution that even comes close to competing with the f-String solution is the modulus operator solution.

Also, I think it’s worth noting how much slower the format function is when the arguments are named rather than ordered. In fact, it’s about as slow as concatenation which I expected to be horrendous. After all, strings are immutable, so concatenation should be pretty bad.

As always, take these performance metrics with a grain of salt.

A Little Recap

With all that said, here are all of the solutions in one unified location:

name = Jeremy
age = 25

# String formatting using concatenation
print("My name is " + name + ", and I am " + str(age) + " years old.")

# String formatting using multiple prints
print("My name is ", end="")
print(name, end="")
print(", and I am ", end="")
print(age, end="")
print(" years old.")

# String formatting using join
print(''.join(["My name is ", name, ", and I am ", str(age), " years old"]))

# String formatting using modulus operator
print("My name is %s, and I am %d years old." % (name, age))

# String formatting using format function with ordered parameters
print("My name is {}, and I am {} years old".format(name, age))

# String formatting using format function with named parameters
print("My name is {n}, and I am {a} years old".format(a=age, n=name))

# String formatting using f-Strings (Python 3.6+)
print(f"My name is {name}, and I am {age} years old")

And with that, we’re done. If you liked this article and want more content like this to hit your inbox, subscribe to our newsletter. Even better, become a member of The Renegade Coder community and earn cool rewards like attribution at the end of an article like this one.

Alternatively, you’re welcome to do your typical online shopping through the following Amazon affiliate links:

As always, I try to pick relevant products that I think will bring you some value. If you have any products of your own that you’d like to me to share, drop them down below in the comments.

In the meantime, why not improve my site metrics a bit by browsing some of the following Python articles:

At ant rate, thanks again for your support, and a special thanks to all my patrons who make this possible. Until next time!

The post How to Format a String in Python: Interpolation, Concatenation, and More appeared first on The Renegade Coder.

]]> 0 18180
Minimum Spanning Tree Algorithms Mon, 02 Sep 2019 15:00:55 +0000

As a fate would have it, y'all are getting yet another article based on topics I'm studying for the qualifying exam. This time, I'm talking minimum spanning tree algorithms.

The post Minimum Spanning Tree Algorithms appeared first on The Renegade Coder.


With my qualifying exam just ten days away, I’ve decided to move away from the textbook and back into writing. After all, if I can explain the concepts, I should be able to pass a test on them, right? Well, today I’m interesting in covering one of the concepts from my algorithms course: minimum spanning trees.

Table of Contents

Minimum Spanning Trees Overview

Before we can talk about minimum spanning trees, we need to talk about graphs. In particular, undirected graphs which are graphs whose edges have no particular orientation. In other words, it’s a graph with edges that connect two nodes in both directions:

Undirected Graph Diagram

If we were to traverse an undirected graph in a special way, we could construct a tree known as a spanning tree. More specifically, a spanning tree is a subset of a graph which contains all the vertices without any cycles. As an added criteria, a spanning tree must cover the minimum number of edges:

Spanning Tree Diagram

However, if we were to add edge weights to our undirected graph, optimizing our tree for the minimum number of edges may not give us a minimum spanning tree. In particular, a minimum spanning tree is a subset of an undirected weighted graph which contains all the vertices without any cycles. Once again, the resulting tree must have the minimum possible total edge cost:

Minimum Spanning Tree Diagram

One final note: minimum spanning trees may not be unique. In other words, there may be multiple minimum spanning trees for a given graph. For example, if edge ED had cost 4, we could choose either ED or BD to complete our tree.

With that out of the way, let’s talk about what’s going on in the rest of this article. In particular, we’ll take a look at two algorithms for constructing minimum spanning trees: Prim’s and Kruskal’s.

Minimum Spanning Tree Algorithms

As mentioned already, the goal of this article is to take a look at two main minimum spanning tree algorithms. Both algorithms take a greedy approach to tackling the minimum spanning tree problem, but they each take do it a little differently.

Prim’s Algorithm

One way to construct a minimum spanning tree is to select a starting node and continuously add the cheapest neighboring edge to the tree—avoiding cycles—until every node has been connected. In essence, that’s exactly how Prim’s algorithm works.

Prim's Algorithm Diagram

In this example, we start from A and continually expand our tree until we’ve connected all the nodes. In this case, we select AB then BC then CD. In the end, we end up with a minimum spanning tree of cost 12.

Of course, we could have always started from any other node to end up with the same tree. For example, we could have started from D which would have constructed the tree in the other direction (DC -> CB -> BA).

As you can imagine, this is a pretty simple greedy algorithm that always constructs a minimum spanning tree. Of course, there is a bit of decision making required to avoid generating cycles. That said, as long as the new edge doesn’t connect two nodes in the current tree, there shouldn’t be any issues.

Kruskal’s Algorithm

Another way to construct a minimum spanning tree is to continually select the smallest available edge among all available edges—avoiding cycles—until every node has been connected. Naturally, this is how Kruskal’s algorithm works.

Kruskal's Algorithm Diagram

In this example, we start by selecting the smallest edge which in this case is AC. To recognize this connection, we place A and C in a set together. Then, we find the next smallest edge AB. In this case, B is not already in the set containing A, so we can safely add it.

At this point, we run into a problem. If we select BC, we’ll create a cycle because B and C are already connected through A. Since B and C are in the same set, we can safely skip that edge.

Finally, we consider the next smallest edge which is CD. Since D is not connected to C in some way, we can add it to our set containing A, B, and C. Since our set now contains all four vertices, we can stop.

Unfortunately, this example is probably not the best because Prim’s algorithm would run similarly if we started from A or C. Of course, drawing these examples takes time, so I recommend checking out Wikipedia for both Prim’s and Kruskal’s algorithms. Each page has a nice animation showing the difference.

Personally, I find this algorithm to be a bit more challenging to grasp because I find the avoiding cycles criteria a bit less obvious. That said, as I’ve seen it in various textbooks, the solution usually relies on maintaining collections of nodes in sets that represent distinct trees. Then, the algorithm only selects two nodes if they are in different trees. Otherwise, drawing an edge between the nodes would create a cycle.

Want to Learn More?

As it turns out, that’s all I have on minimum spanning trees. If you liked this article and you want to see more like it, consider becoming a member. Membership is what keeps these articles free, so if you got any value out of this article today, think about others who may as well.

If you can’t support the website right now, you can always hop on the mailing list, so you continue to receive the latest articles in your inbox.

Otherwise, check out some of the following relevant books:

While you’re here, check out some of the following articles:

Well, that’s all I have for now! Thanks for stopping by.

The post Minimum Spanning Tree Algorithms appeared first on The Renegade Coder.

]]> 0 18029
Driving Is the Worst Fri, 30 Aug 2019 14:00:33 +0000

As someone who used to think of driving as the epitome of freedom, I've grown to realize that driving is the worst. Join me in this fun rant!

The post Driving Is the Worst appeared first on The Renegade Coder.


While on my way to camping last week, I listened to a pretty great podcast on driving which got me to thinking: driving is the worst. Naturally, I decided to do a little rant piece about, so let’s see how things go.

Table of Contents


Before I dig into this inflammatory piece, I want to start off by saying: I love driving. That’s right! I know it goes contrary to the title, but I really do enjoy getting into a car and driving around.

For me, driving has always been a symbol of freedom. The day I turned 16 I ran to the DMV to get my permit. Then six months later, I returned to claim my prized drivers licence.

From there, I used that license to do a lot of amazing things like getting and maintaining a job. In addition, that license allowed me to visit friends and move across the country. In fact, I’ve probably driven through 15 states in the last 9 years, and I wouldn’t give that up for anything.

That said, there’s so much more to driving than traveling from place to place, and that’s sort of where my love for driving ends. As of late, I’ve grown to hate driving more and more, and this piece is sort of a tribute to that hate. At any rate, let’s get into it!


Every once in awhile, I like to write these sort of rant pieces because they make me feel better about myself. As a result, I don’t necessarily expect this piece to come off as an honest critique. Instead, it’s more of an old man rant.

In the following subsections, I’ll list some off the reasons I hate driving. That said, I don’t intend to go into a ton of detail. As a result, if you want to hash things out, let’s talk about them in the comments.

Navigation Is a Nightmare

As someone who likes to take road trips from time to time, I find some places hard to navigate. After all, there’s no standardization. Some intersections have stop signs or stop lights while others forgo stopping altogether by introducing yield signs and a roundabout. Some intersections have three roads while others have five. Some roads maintain a constant number of lanes while others contract and expand like a set of lungs.

All this chaos can make for some pretty hectic driving—especially for a newcomer. After all, there’s a lot you have to worry about as a driver. What’s the speed limit? Which lane do I need to be in? How much time do I have to get over? Is it rush hour?

Even with the aid of GPS, navigation can be challenging. How far is 200 feet exactly? Is that the next intersection or the one after it? Again, what lane do I need to be in? I can’t see the damn labels on the road with all this traffic.

Then, there are roads that make absolutely no sense. For example, there are several roads out there that grant turning cars right-of-way by adding stop signs to the straight lanes. When you inevitably stop because it’s what you do when you want to turn, other drivers throw you the finger because you’re wasting time. That’s just bad road design. It doesn’t surprise me at all when people get into crashes as a result.

People Are Idiots

As I’ve written about quite a bit already, people are stupid—especially in Columbus. When stupid people get into cars, they don’t suddenly gain 30 IQ points. They’re still stupid, and that translates into how they drive on the road.

Think about it. How often do you see someone texting and driving? Or at the very least, fiddling with their phones? I don’t know what they’re doing in there, but it’s quite literally constant.

Some days I can’t wait for our artificial intelligence overlords to take over, so at least crossing the street wouldn’t feel like a suicide mission. Honestly, I catch myself staring in my rearview mirror every time I stop because I don’t trust anyone to be paying enough attention to also stop.

Driving Is a Job

How much time do you think you waste a day driving? As someone who doesn’t drive regularly, it’s close to zero. However, when I used to have to drive for work, I wasted at least an hour a day sitting behind the wheel. That’s time I’m never getting back.

Ironically, there are tons of people out there getting paid to do what we do out of necessity. For instance, there are bus drivers, truck drivers, cab drivers, Uber and Lyft drivers, and even train “drivers.” How is that so many of us have to commute to work by car for nothing?

Let’s not forget that driving is a huge opportunity cost. For me, the hour a day I used to lose driving is now taken up by an hour of walking a day—something that has health benefits. Instead of driving, we could be doing literally anything else. As a result, we should be asking ourselves: “what is our time worth?” If you think you’re worth $20 an hour, you’re losing $20 every time you step into you car.

Driving Is Wasteful

Almost all of my complaints in this article are individual ones. In other words, most of my complaints are about things that affect me personally. Of course, driving has problems that are even larger than the individual. In particular, they’re pretty bad for the environment.

Personally, when I think about cars, I think about all that gas I’m burning and pumping directly into the atmosphere. That said, that’s only a fraction of the problem. A lot of people now rotate through cars every few years by leasing and upgrading. How is that not wasteful? After all, if the demand for new cars is high, we’ll continue to manufacture them, and manufacturing isn’t exactly green either.

To make matters worse, think about all the engineering that goes into crafting the latest model of your favorite car. In terms of features alone, we’re talking about a lot of wasted time by people who have to find new ways to cram in the latest tech into the dashboard. Who needs a motorized rearview mirror or automatic car doors? Some company spent the time and energy to design and manufacture those features. What a waste.

Cars Are Expensive

Living in America means you almost certainly need to own a car. Of course, I can’t think of a single necessity besides housing that is on the same order of magnitude in terms of cost. In fact, a car alone will likely set you back $20,000. If you can’t afford to pay it, you’re looking at an even steeper loan with interest.

Of course, paying off a car is only one of the expenses. Don’t forget about routine maintenance like oil changes and tire rotations. In addition, you have to fill up the gas tank regularly which can run over $2.50 a gallon. Likewise, you have to pay for car insurance, and that ain’t cheap.

Occasionally, you might even have to shell out for a larger repair. Perhaps you lose the transmission after 100,000 miles. That’s not going to be cheap to replace. Or worse, you get into an accident. Now, you have to replace the entire car as well as pay some medical bills—assuming everyone survives.

Oddly enough, we associate cars with freedom, but that couldn’t be further from the truth. With cars being such an expensive necessity, you have far less freedom to do what you want with your money.

Infrastructure Is Crumbling

To add insult to injury, the infrastructure that we drive our cars on is crumbling. As someone from Pennsylvania with very high Department of Transportation taxes, I never really noticed this issue beyond a few potholes. However, now that I’m in Ohio, my wife and I drive on terrible roads often, and I can’t imagine that’s great for the car.

As mentioned already, car repairs are expensive, and terrible roads can exacerbate that issue. If you’re like me and you own an older car, these roads can send you back to the mechanic often.

Of course, when the state finally gets around to patching things up, they usually take down a street for most of the summer. As a result, a quick trip to the store or work can suddenly become a nightmare as you have to find an alternate route or deal with the sudden increase in traffic. Ain’t nobody got time for that!

Cars Take Up Space

How often do you drive your car at capacity? If you’re like me, it’s almost never, and I have a pretty small car. As you can probably imagine, there are tons of cars on the road right now that aren’t full. In other words, they’re wasting space.

To accommodate for this inefficiency, we build massive parking lots and garages, so these excessive cars have somewhere to stay. In addition, we continue to add lanes to expand our capacity for cars on the road. Almost our entire infrastructure is designed for cars—not people.

In many cities, expanding the roads is not practical as we can’t move buildings. As a result, gridlock is almost guaranteed. Hell, even in cities where you can expand the roads like Atlanta, there are still several hours a day dedicated to gridlock. Seriously, Atlanta traffic is brutal.

Pedestrians Are An Afterthought

As someone who walks to work now, I can sometimes find navigating the streets a challenge. In particular, I’m talking about navigating the streets along with all the other modes of transportation: cars, bikes, scooters, etc.

Each day, I have to worry about being hit as I cross through an intersection because drivers aren’t paying attention. It’s almost like cars have become so ubiquitous that drivers couldn’t even imagine that people would walk anywhere, and it’s depressing. Not only do I have to practice defensive driving, but I also have to practice defensive walking just to get to work.

To put this into perspective, I cross the road probably 8 times a day, and I have to worry about being hit about half of the time. In general, roads that are closer to the highway are just more dangerous for me because people come flying off the exits without looking. As a result, I have to be aware of cars more than they’re aware of me. It sucks.

Bringing It Home

After all this ranting, what’s the takeaway? Well, sometimes I wish I were living somewhere with better infrastructure for humans. In particular, I would love to live on a block that didn’t have any cars driving through it. Or at the very least, I’d like to live somewhere with enough public transportation to prevent me from needing to step out into the street.

Having lived in places like Atlanta, Columbus, Erie, and the UK, I’d have to say that the US is just doing the whole driving thing wrong. We have absolutely no infrastructure setup for humans. Instead, everything is setup for cars. Think about it. Almost every business now has some form of drive-through or delivery service in addition to a parking lot that sits adjacent to a major road.

Forget walking anywhere. There’s just no way it’s practical with the way cities sprawl now. If you want to get anywhere, you gotta hop in a gas guzzling killing machine. There’s really no way around it, and that’s just sad to me.

Hopefully, we find some way to bridge the gap to more people friendly infrastructure. Until then, I’ll keep an eye out for the guy barreling toward me while texting, and maybe I’ll live long enough to see a new age of travel.

What About You?

With all that said, how do you feel about driving? Is it something you do out of necessity like me, or do you enjoy it? If you could change anything about the way we drive, what would it be?

At any rate, thanks for hearing me out! Naturally, I’ve written about driving in the past. In fact, I’ve ranted quite a bit about drivers in Columbus, and I’ve even talked about what it’s like to get rid of a car and share one with your partner.

If you’d like to support the site, you’re welcome to become a member of the community. Alternatively, you can always hop on the mailing list. Beyond that, I always like to share a few relevant books for you avid readers out there:

As always, thanks for taking some time to visit The Renegade Coder!

The post Driving Is the Worst appeared first on The Renegade Coder.

]]> 0 17963
Yet Another Way to Learn Recursion Mon, 26 Aug 2019 14:00:29 +0000

As someone who covers a lot of beginner concepts, I've always sort of avoided one of the trickier concepts: recursion. Well, today I decided to take a stab at it.

The post Yet Another Way to Learn Recursion appeared first on The Renegade Coder.


Every semester, I pass around a survey to get some feedback on my teaching. This past semester someone finally gave me an idea for a new article. In particular, they wanted to learn some more about recursion, so I figured I’d put together some tips.

Table of Contents

Recursion Overview

For those of you that might be learning recursion for the first time, I figured I’d provide a bit of an overview of the concept.

In particular, recursion is a problem solving technique that relies on solving smaller subproblems. In other words, instead of solving a problem directly, we continue to break the problem down until we get to some smaller problem that we can actually solve. Then, we use the answer to the smallest subproblem to work our way backwards until we have the answer to our original question.

For example, let’s say we want to compute 26. Normally, we would break this down into repeated multiplication. In other words, we would take 2 and multiply it by itself 6 times to yield 64. In Computer Science, we call this problem solving technique iteration, and we usually see it in the form of a loop:

def iterative_power(base, exponent):
  product = 1
  for i in range(exponent):
    product *= base
  return product

print(iterative_power(2, 6))

Of course, what if we already knew the answer to some smaller subproblem. For instance, what if we knew that 25 is 32? Then, we could directly compute 26 by multiplying 25 by 2. That’s the idea behind recursion:

def recursive_power(base, exponent):
  if exponent == 0:
    return 1
    return recursive_power(base, exponent - 1) * base

In this article, we’ll take a look at a different way of thinking of recursion. Hopefully, it helps you understand the concept better than before.

Why Is Recursion So Hard?

While functional programming is currently making a comeback, it hasn’t had a huge impact in the way we learn to code. As a result, most folks start coding with a C-like imperative programming language. For example, I got started with Java and moved into languages like C, C++, C#, and Python.

Unfortunately, the downside of learning languages like C is that we’re sort of constrained in how we think about problem solving. In other words, the tool set that is provided to us in these languages is largely biased toward branching (i.e. if statements and loops).

As a result, the intuition behind recursion isn’t built in from the start. Instead, we’re forced to introduce recursion using contrived examples that tie back to iterative solutions. Otherwise, how else would we relate.

In addition, imperative languages like C require a lot of overhead before recursion can be introduced. For instance, you probably had to learn concepts like variables, branching, and functions before you could even start thinking about recursion. In fact, I wasn’t personally introduced to the concept until my first data structures course.

Altogether, it can be hard to grasp recursion because it requires your understanding of coding to be turned on its head. Luckily, there are ways to break the cycle (pun absolutely intended).

Learning Recursion Through Design by Contract

Recently, I was training to teach a software components course at The Ohio State University, and one of the topics they covered in that course was recursion. Of course, I was already quite familiar with recursion at the time, but I thought the way they taught the subject was really elegant. As a result, I figured I could pass that method on to you. That said, we’ll need to tackle Design by Contract first.

Introduction to Design by Contract

I apologize if I’m repeating myself a bit as I have written a bit about Design by Contract in the past—mainly in reference to JUnit testing. Naturally, I think I’m a slightly better writer now, but feel free to refer to that article as well.

At any rate, Design by Contract (DbC) is a programming philosophy where we think about functions in terms of contracts. In other words, we want to provide some sort of guarantee to our users when they use one of our functions. In particular, we ask our users to execute each function under certain conditions (aka preconditions). As a consequence, we promise that each function will behave a certain way (aka postconditions).

DbC is important in recursion because it allows us to specify exactly what a function will do under certain conditions. For example, the power functions we defined earlier work only as long as we specify a few preconditions:

  • Both parameters must be integers (could be taken care of with some type hints)
  • The power parameter cannot be negative

As a result, we promise that both functions will return the base raised to some power. If a user enters invalid inputs, we don’t make any promises as they’ve clearly broken the contract. Of course, we can always provide some sort of input verification to prevent nasty bugs, but that’s outside the scope of DbC.

Free Lunch for All

At OSU, we introduce recursion by ignoring the idea of recursion altogether. Instead, we leverage what we know about Design by Contract to start implementing recursive functions implicitly.

For example, let’s take another look at this power function we keep talking about:

def power(base: int, exponent: int) -> int:
  """Computes the base ^ exponent.

  Precondition: exponent >= 0
  Postcondition: base ^ exponent
  return FreeLunch.power(base, exponent)

In this example, we introduce a new power function from a magical library called FreeLunch. As far as we’re concerned, this new power function is exactly the same as the one we have written—same exact contract.

Now, for the sake of argument, let’s say that this FreeLunch power function has a requirement: its input must be “smaller” than the input of our power function. What can we do to ensure this works?

Well, if we decrease the exponent, we can add it back by multiplying the base (i.e. x5 = x4 * x). Let’s try that:

def power(base: int, exponent: int) -> int:
  """Computes the base ^ exponent.

  Precondition: exponent >= 0
  Postcondition: base ^ exponent
  return FreeLunch.power(base, exponent - 1) * base

At this point, how do we go about verifying that this works? Well, let’s try some inputs. For example, we could try 26 again. If we trace over the code, we’ll notice that we call FreeLunch.power(2, 5) which is a completely valid input. In other words, we’ll get 32 back which we multiple by 2 to get 64, the correct answer.

That said, are there any inputs that would fail? Absolutely! Since the FreeLunch power function shares the same contract as our power function, there are inputs which are invalid. For example, we should avoid any situation in which the FreeLunch power function is passed a value smaller than 0:

def power(base: int, exponent: int) -> int:
  """Computes the base ^ exponent.

  Precondition: exponent >= 0
  Postcondition: base ^ exponent
  if exponent == 0:
    return 1
    return FreeLunch.power(base, exponent - 1) * base

Now, we can be certain our power function works.

There Is No Free Lunch

As you can probably imagine, implementing the power function in this convoluted way was just an exercise to trick you into using recursion. In other words, we can completely remove the FreeLunch class above, and we’d have a fully functioning recursive solution:

def power(base: int, exponent: int) -> int:
  """Computes the base ^ exponent.

  Precondition: exponent >= 0
  Postcondition: base ^ exponent
  if exponent == 0:
    return 1
    return power(base, exponent - 1) * base

Now, the question is: why would we go through all this effort to introduce recursion? After all, almost every other recursion tutorial leverages some sort of stack. Why don’t we do that?

While it’s perfectly valid to teach recursion using the stack, it’s often quite cumbersome for students. For example, imagine tracing through the power function above without using our FreeLunch trick. If we provide two random inputs—say a base of 2 and an exponent of 6—we would have to trace through each power function call until we reached the smallest subproblem. On paper, that’s six traces for one simple example!

When taught this way, students can often find themselves getting lost in the recursion as they try various inputs on their program. If they were to instead suspend their disbelief and trust in the contract, they could prove their function works on a single pass. Of course, they’ll need to pay some attention to their inputs (see mathematical induction).

Recursive Roots

Now that we’ve seen some examples, I want to talk a little bit about where recursion comes from. After all, recursion is often this scary subject that seems to appear when convenient in Computer Science lectures. Luckily, it has a much more interesting history than that.

Remember how we looked at a power function previously? That was no accident. In fact, there loads of mathematical formulas which can be written recursively. For instance, the power formula looks as follows:

an = an-1 * a (if n > 0)

Naturally, an can continually be decomposed until the exponent is either 1 or 0 depending on how we’d like to terminate our recursion. In our examples above, we ignored when n = 1 because n = 0 gives us 1 which works out fine. In other words, adding an extra case for n = 1 has no effect on the result.

Like power, there are several other recursive formulas that you probably already know. For example, the Fibonacci sequence is defined by a recursive formula:

an = an-1 + an-2

To make sure this formula works, we have to define the first two terms. Then, everything works out fine. Depending on who you ask, the first two terms could be 0 and 1 or 1 and 1. Regardless, both pairs of numbers work.

If we want to then compute any arbitrary term in the sequence, we decompose the original function until we hit either of our base cases. For example, the following diagram illustrates how we would compute the fifth term in the Fibonacci sequence:

We can argue about the efficiency of a recursive algorithm like this all day, but this is a valid way to solve the problem. Instead of solving the problem in incremental steps, we break the problem down into smaller problems until we find a problem we can solve. Then, we use that result to work our way backwards until we have our final answer.

Recursive Structures

Now that we’ve looked at recursion through the lens of mathematics and Design by Contract, the question becomes: how do we recognize problems where recursion would be beneficial? In other words, are there problems that have some form of recursive structure? Let’s talk about it.

As it turns out, there are recursive structures all around us. For example, the Fibonacci sequence is explicitly defined as a recursive formula. Of course, there are other types of recursive structures. For instance, the tree diagram above is a recursive structure. After all, each call to “fib” creates yet another tree. In other words, there are trees inside trees.

Outside of technology, there are other examples of recursive structures like fractals which are collections of geometric shapes that retain their structure at any scale. For those of you familiar with the Triforce, it is a perfect example of a simple fractal: a triangle made of triangles.

Likewise, there are several everyday recursive structures like directories (folders containing folders) and onions (onions containing onions). In other words, hierarchical and nesting structures are usually good indicators of recursion.

From these examples, are there any sort of patterns we can recognize? Well, of course! The key here is to observe the structure of a problem. Is the problem itself made up of similar problems? If so, recursion is probably the way to go. If not, it might make more sense to try something else.

Famous Recursive Algorithms

With all that said, I think it’s helpful to put together a short list of famous recursive algorithms for inspiration purposes. Feel free to share some of your favorites in the comments:

And with that, I think we’ve covered about everything. If you have any questions that weren’t covered in the article, feel free to direct them to the comments below.

See Recursion

If you want to learn more about recursion, I recommend checking this really awesome article called Yet Another Way to Learn Recursion (sorry, I had to make at least one recursion joke). Otherwise, thanks for stopping by!

While you’re here, you should consider becoming a member The Renegade Coder community. We’re small, but we’re making an impact. If you still need time to decide, you can stay in touch through our mailing list.

While you’re here, check out some of these relevant books:

If you’d like to stick around, I have plenty of other articles for you:

Once again, thanks for your support. Every little bit goes a long way!

The post Yet Another Way to Learn Recursion appeared first on The Renegade Coder.

]]> 0 17751
5 Great Strategies for Learning to Code Fri, 23 Aug 2019 14:00:33 +0000

As a student, I know that you can't expect a teacher to do the learning for you, so I've put together a list of 5 strategies for learning to code.

The post 5 Great Strategies for Learning to Code appeared first on The Renegade Coder.


As a teacher, I get a lot of questions from students on how to learn more about programming outside of class, and until now I haven’t had a really good answer. At long last, I’ve collected my thoughts and put together this list of strategies for learning to code.

Table of Contents


Right now, I’m preparing to teach a software course where the primary programming language is Java. Of course, not all of the students coming into the course know Java. As a result, they’ll have to get up to speed rather quickly. Naturally, this article is for them.

In addition, I’ve had several students email me in the past asking for coding resources. These are students who aren’t necessarily going to go into Computer Science, but they still want to learn some code for their field (Math, Finance, Business, etc.). As a result, this article is also for them.

Finally, I’m sure there plenty of people out there who are just looking for more support as they learn to code. If that’s you, this article is also for you.

The List

Without further ado, here’s my list!

#1: Join Coding Communities

I’ll come right out of the gate and say it: no article is ever going to give you an up to date list of the best resources for learning to code. As a result, I always tell people to get involved in coding communities.

Personally, I’m partial to Twitter (where I follow the #CodeNewbie and #100DaysOfCode hashtags) and, but there are literally hundreds out there. For instance, I’m familiar with Medium as a popular blogging platform among developers as well as FreeCodeCamp which now has its own blogging community.

Once you find a few communities you like, I recommend building up a list of your favorite contributors. That way, you can point others to awesome content. If you’re lucky, your favorite contributors will start building a nice following which means more awesome content for you. It’s a wonderful feedback loop!

To be honest, I’ve been really bad about this because I tend to focus mostly on creation rather than consumption, so feel free to recommend your favorite contributors in the comments.

#2: Complete Coding Challenges

In the wonderful age of the internet, there are now a ton of websites which offer gamified education through coding challenges. In general, these sort of platforms provide a series of problems in increasing difficulty which can be solved for some form of internet points (aka bragging rights). In some cases, these internet points can help you score a job which is a nice bonus.

While I’m not big into the coding challenge craze, I have toyed around on a few sites for my own enjoyment. For instance, I’m quite fond of HackerRank which is one of those sites where you can tackle some practice problems while gaining exposure to potential employers. As far as I can tell, they offer problem sets for a variety of languages including C, C++, Java, Python, and Ruby.

If you’re more interested in web development, I recommend FreeCodeCamp (again). Personally, I used the website to try to brush up on some JavaScript, so I could learn a few useful libraries like WebGL for 3D graphics and D3 for data visualization.

In addition, I’m familiar with at least one niche coding challenge site called CodingBat for people learning Java or Python. If you’re just looking for code practice, CodingBat is the way to go. There’s no signup or internet points to worry about.

Beyond that, a quick Google search yields a few additional resources like:

  • CodeWars: Achieve Mastery Through Challenge
  • Exercism: Code practice and mentorship for everyone
  • HackerEarth: Programming Tutorials and Practice Problems
  • Coderbyte: Improve your coding skills

As always, if you know of any coding challenge websites that you think others could benefit from, share them in the comments.

#3: Use Q&A Forums

Sometimes when you’re learning to code, you just want your questions answered. In other words, you don’t want to have to sift through blogs or documentation to get a recommendation on how to solve a problem. Thankfully, there a lot of resources for people who just want answers to their questions.

Perhaps the most infamous coding Q&A website on the internet is StackOverflow. In general, it’s a forum-like website where you can ask questions and get answers from people in the community. If you’ve ever Googled a coding question, you’ve probably found yourself there.

Of course, there are other Q&A platforms on the internet including Quora which is a bit less coding oriented. That said, I think the platform excels in areas that StackOverflow doesn’t like coding philosophy questions (i.e. What are the best programming practices and coding standards independent of programming languages?).

In addition, there’s always Reddit. Unfortunately, I haven’t personally tried to use that platform as it’s also a bit infamous. It’s really too bad there isn’t a benevolent Q&A platform as far as I know, but I think you can still get some value out of these services regardless.

#4: Explore Open-Source Projects

One thing that I think a lot of new learners overlook is the value of open-source code. In particular, I mean having access to a near limitless amount of production quality code in the wild.

Of course, there’s always a bit of a barrier to open-source code as many platforms require some knowledge of version control. Fortunately, you don’t need to know version control to be able to browse code. Seriously!

Right now, you can go on GitHub and explore the most popular repositories by topic. In other words, if you’re interested in Python, you can find a list of active projects written in the language like Flask or Django. As a consequence, you’ll be able to explore real code and get a feel for how real projects are written and managed. If you want, you could even fork your own version and make some changes.

While I was writing this article, I noticed that GitHub already has a “Learn to Code” collection which is loaded with awesome resources like this Project Based Learning collection and this Python Programming Challenges collection.

Naturally, GitHub isn’t the only open-source hub on the internet. You may also get some value out of BitBucket and GitLab. Of the two, I’ve only used BitBucket which used to be the only place to get free private repositories. That said, GitLab has been gaining a lot of traction since Microsoft took over GitHub, so it may be worth checking out.

#5: Never Give Up

Perhaps the best tip I can give to learners is to stick it out. Unfortunately, learning to code is hard because a lot of people have purposely made it that way. In essence, I’m talking about gatekeeping.

For whatever reason, there’s a very vocal minority in the tech community that wants to decide who can and can’t be in the community based on arbitrary criteria. For instance, you might be compelled to quit after someone claims you aren’t a real coder because you use HTML and CSS.

Even as an instructor, I catch nasty comments from elitists every now and then. In fact, I’ve even made an entire Wall of Shame for some of the comments I’ve gotten. Of course, I wouldn’t recommend you do the same as it’s a lousy coping mechanism. That said, I do think it’s helpful to see examples of the types of things people say to each other under the guise of internet anonymity. In other words, empathy is lacking in the community.

All-in-all, as long as you continue to focus on your growth, you’ll learn what you need to learn. And if not, hopefully you can find a community of people to support you. As always, I’m open to mentoring anyone who needs a hand. Just give the word!

Best of Luck

And with that, all I have to say is best of luck!

Once again, this is the part of the article where I shamelessly plug my membership site. If you’re into that sort of thing and can toss a couple bucks my way, I’d appreciate it! Alternatively, I’d love it if you hopped on my mailing list. That way, we can stay in touch.

While you’re here, check out some of these relevant books:

In the meantime, I have plenty more content where this came from. To be honest, I don’t do a lot of list pieces like this or general opinion pieces for that matter. That said, I love to talk about code, so maybe these beginner-oriented articles might interest you:

Well, that’s all I got for now. Thanks again for your support, and I hope to see you around.

The post 5 Great Strategies for Learning to Code appeared first on The Renegade Coder.

]]> 2 17820
Looking Back on My First Year of Teaching Mon, 19 Aug 2019 14:00:01 +0000

With my first year of teaching in the books, I thought it would be fun to take a look back on what I liked and what I didn't like.

The post Looking Back on My First Year of Teaching appeared first on The Renegade Coder.


While I often reflect every semester of teaching, I thought it would be fun to look back on the previous year as a whole. In other words, let’s take a look back at my first year of teaching. But first, I recommend checking out the three reflections I’ve already written:

Of course, I’ll be reviewing everything below, so feel free to jump ahead.

Table of Contents


In case you haven’t read any of my reflections, I figured I’d share a bit about the courses I taught over the past year.

For starters, I taught two classes: CSE 1223 and CSE 2221. In my first two semesters, I taught CSE 1223 which is an introductory programming course in Java for pre-majors and non-majors. Then, I moved into a training position as a grader for CSE 2221 which is a software components course for pre-majors.

Over the course of three semesters, I graded somewhere around 1000 projects, 800 labs, 800 homework assignments, and 240 exams. In addition, I worked with almost 120 students over 40 weeks for a total of roughly 280 contact hours. That’s a lot of work!

In terms of compensation, I was contracted for about $20,000 a year before taxes, not including summers. With the addition of summers, I made roughly another $5,000. On top of that, I was guaranteed several benefits including a tuition waver, healthcare, vision, and dental.

Ultimately, I’ve been teaching for about a year now, and I plan to continue teaching indefinitely.


At this point, I want to talk about some of the things I loved about teaching this past year.

The Feedback

One of the things I really liked about teaching was getting real-time feedback on my work. If students didn’t understand something, they’d let you know. In fact, some of my favorite instances of feedback came during one-on-one interactions during labs and office hours. If something wasn’t clear, I always had a chance to start over.

In addition, my students were always great at filling out any feedback surveys I sent them. For instance, each semester I sent out a Google Form for feedback which I wrote about in my regular reflections. Likewise, students were asked to fill out a Student Evaluation of Instruction each semester, and those were always a joy to get back.

Here are some of my favorite bits of feedback from the last year:

I really enjoy [Jeremy’s] teaching style. [He] seemed to actually enjoy teaching which seems to be a rare occurrence. I felt like [he] tried to teach so that I actually understood Java which I think is the most important thing. I enjoyed the coding tangents where [he] would detail some of how java is used in the real world.

Tony, Fall 2018

I thought that Professor Grifski did really well teaching the class. I came into Java without having any coding background while nearly half of my class already did. However, he still spent time going through each detail which quickly allowed me to catch up. Despite the numerous times that I emailed him questions, he answered promptly and patiently. I also really appreciated the fact that he didn’t simply assign grades to our assignments, but provided comments that would point out mistakes and how they could be corrected and avoided in the future.

Anonymous, Fall 2018

I appreciated [Jeremy’s] availability in both office hours and labs. I could tell [he was] passionate about teaching the class and that rubbed off on me trying to learn the material. Having a teacher/professor that enjoys their work makes a contagious atmosphere and makes the class more enjoyable for everyone in the classroom.

Anonymous, Spring 2019

Honestly, Professor Grifski may hands down be the best professor I had this semester. He truly cared about his students not only learning the material but the “how and why” of coding. Its only now that we begin to talk about Objects and Classes that he seems to light up more. I believe the more theoretical the coding gets, the more he enjoys it. He gives students the benefits of the doubt and pushes them to think for the answer rather than giving it to them. I hope he teaches more upper level classes in CSE so I can schedule him.

Anonymous, Spring 2019

Excellent knowledge resource. I found myself listening intently every time anyone of close proximity asked [Jeremy] a question, and picked up a lot of good information that way.

Anonymous, Summer 2019

Sometimes it’s nice to be able to look back on these bits of feedback when I’m having a bad day.

The Light Bulb Moments

I’m sure every teacher says this, but I live for that light bulb moment. In particular, I like seeing students suddenly understand a concept during a lecture or lab.

As a developer myself—in both the StrengthsQuest and the coding sense of the word—I understand what it’s like to struggle through new concepts. As a result, I take great satisfaction in being able to ease the cognitive load a bit for students.

Over the past three semesters, I’m not sure I’ve seen the light bulb moment often, but I can think of a few students who have appreciated my time the most. In general, these are students that I see regularly in labs and office hours who have an insatiable curiosity. In many cases, they want to know more than they need to know to get through the class, and that’s always satisfying as a teacher. After all, isn’t that how education is supposed to work?

At any rate, I’m looking forward to many more light bulb moments as I refine my teaching skills.

The Temporal Volatility

You may recall that one of the reasons I left industry is the predictability. In other words, there were really no (good) surprises in industry. For example, I always knew exactly when I was going to clock in, and I could assume roughly when I would clock out. And, that reality never changed.

One of the things I missed about academia was the volatility. In other words, I missed having a schedule which didn’t follow the 9-5 grind. After all, variety is the spice of life.

Now that I’m back in it, I have to say that I really love the volatility. In particular, there’s nothing more refreshing than know that a semester will eventually end. As a result, I always have something to look forward to: change.

Obviously, volatility isn’t for everyone, but I love it! In fact, I sometimes wish there was a bit more volatility—particularly spatial volatility. For example, I wish there was a little bit of travel involved in my job. I’d love to give guest lectures around the globe.

All that said, I can’t really complain. The regular change of scenery is really nice, and I wouldn’t give that up for almost anything.


As much as I’d love to say that teaching is always amazing, I’d absolutely be lying. There are parts of the job that I haven’t loved as well.

The Pay

If we’re looking strictly at monetary compensation, I’m contracted for 20 hours a week for about 15 weeks a semester. Over the course of a year, that would be about 30 weeks of work at a rate of about $33 an hour (20,000 dollars/year ÷ 30 weeks/year ÷ 20 hours/week).

Of course, by the time I see the paychecks, they’re about $1,600 a month or more like $20 an hour on the high end. While that’s nothing really to complain about, I do feel like its not enough money to live on considering that I have to stretch that over a year. If I’m unlucky enough not to score a summer job, I have to stretch the money even more.

Also, I know I’ve complained about this quite a bit, but people in my field can make significantly more money in industry. For instance, I was making about $75,000 a year before I quit which is about $36 an hour. And when I went home, I didn’t bring my work with me. Now, I work all the damn time.

To me, it just seems silly that universities act like they’re doing you a service for waving tuition (which is already unreasonably high) and for letting you do PhD quality work for next to nothing. And when I do research on the subject, I get a lot of that toughen up bullshit from elitists in the field.

To make matters worse, I probably work close to 100 hours a week where a third of that is just teaching. How am I supposed to survive on $20,000 a year when I’m working enough to earn an order of magnitude more than that. That said, I wouldn’t be caught dead going back into industry.

The Disrespect

Unlike most people in power, I don’t really get any joy out of being in control. That said, I do appreciate respect, and I always extend it to my students. Unfortunately, it’s not always reciprocated.

Over the past three semesters, I can think of at least 3 students who tried to manipulate me in some way to get what they wanted. In many cases, these were students who didn’t regularly attend classes or office hours but wanted breaks when things didn’t go their way.

As a teacher, this can be really frustrating. After all, I try to accommodate everyone’s needs, but some students clearly just want to game the system. For instance, I’ve had students try to work around me by going to my superior or leveraging the fact that I have a superior to get what they want. It’s like the student embodiment of the phrase “I want to talk to the manager.

In general, however, as long as I extend respect to my students, they tend to extend it back to me. Thankfully, I’ve had to deal a lot less with disrespect than you’d think.

The Authority

As long as I can remember, my parents treated me like an adult, so I can’t stand it when someone treats me like a kid. Naturally, I thought the move into academia would grant me more of the autonomy I crave, and for the most part I was right. That said, I still run into the occasional micromanager.

Over the past three semesters, I have had control over everything except the course content. Of course, I’m totally fine with teaching the material that is given to me. What I don’t like is someone telling me how to do my job.

To be honest, this hasn’t been much of an issue because no one really has the time to micromanage their underlings. That said, I have experienced a few ugly conversations with some professors over how I’ve chosen to handle my classroom.

To me, the worst part about being managed is the lack of room for dissent. After all, the power dynamic essentially guarantees that any sort of dissonance will go poorly for the managed—not the manager. In my case, fighting with a professor could result in reduced opportunities with other professors as word gets around the department. As a result, it’s to my advantage to do what I’m told, and that just doesn’t mesh well with my personality.

Fortunately, I haven’t run into this nearly to the extent that I’ve experienced it in industry. That said, it’s something I will forever despise.

Here’s to Many More Years of Teaching

With my first year of teaching out of the way (ignoring some undergraduate teaching and grading I’ve done in the past), I’m happy to say that I like the gig. It sure beats being strapped to a desk 40 hours a week.

At any rate, time to make my usual plug for support. In particular, I’d love it if you jumped on bandwagon and become a member of The Renegade Coder community. If not, at least hop on the mailing list, so I can pester you once a week with links to my latest articles.

Likewise, here are a few books for folks who might be interesting in teaching:

While you’re here, you might want to check out the rest of the reflections:

These articles go quite a bit more in depth than I did here, so I recommend reading them if you have the time. Each article is just over 3000 words, so there’s a lot to digest.

If nothing else, thanks for stopping by! I appreciate the support, and I hope you’ll come back in the future.

The post Looking Back on My First Year of Teaching appeared first on The Renegade Coder.

]]> 0 17843