I
have seen it time and time and again. A novice programmer sits down at the computer with the goal of writing the next big computer application. However, they do not have much experience putting code to screen and end up writing an ever-expanding network of while loops and if statements akin to a maze of paths through an unkempt garden. If one wanted to implement a gazebo in such a garden, they would surely have to rewrite much of the logic. If you have ever found yourself writing code like this, fear not. In this post, I will explain how you can use functional programming concepts to more effectively organize your code.
When you wrote that maze of loops and if statements, you wrote in a style known as imperative programming. In imperative programming, operations are executed line by line, and each operation modifies the state of your program (your variables) in some way. To contrast this, functional programming revolves around the concept of functions, which are discrete chunks of instructions that can be reused throughout a program. You might have heard of these before but never bothered to learn how they work. However, you should consider them to be an indispensable tool in your programming arsenal. Functions mitigate a number of problems, such as the existence of duplicate code and the inability to test particular features of the code. Most importantly, functions in functional programming do not modify global state—they merely run a sequence of instructions on an input and produce an output. Even when interspersed with imperative code, functions present a powerful utility for the betterment of your code.
You might be perfectly comfortable with writing the same code in multiple places if it gets the job done. However, this is not a good way to program, and there’s a very simple argument why. Say you’re writing a program that appends the same string to an input in multiple places. For example, your program could be keeping an inventory of the various things you have stored away. The user inputs something such as “apples”, and the program will print “You have 2 apples.” A naive way to implement this would be the following:
string haveText = “You have”
int apples = 3
int pears = 2
int bananas = 10
while true do
string input = getInput()
if input == “apple” do
string plural = (apples != 1 ? “s” : “”)
print(haveString + “ “ + apples + “ “ + input + plural)
else if input == “pear” do
string plural = (pears != 1 ? “s” : “”)
print(haveString + “ “ + pears + “ “ + input + plural)
else if input == “banana” do
string plural = (bananas != 1 ? “s” : “”)
print(haveString + “ “ + bananas + “ “ + input + plural)
else
print(“You have no “ + input + “s.”)
end
end
The problem with this code is that we perform the same operation (haveString + “ “ + something + “ “ + input) three times. This becomes a lot to manage. For instance, say you wanted to change the output to something of the form “There are 3 apples in your inventory”. You would have to update the code in three locations in order to implement this change.
Testing one’s code is a great way to make sure it does what it is expected to do and does not contain any bugs. In a purely imperative programming approach, you would have to start your application and test it manually in order to make sure your code works. While this might work fine for a small program, in larger programs, it is often preferable to automatically test parts of the code rigorously in order to make sure those individual pieces work. If the individual pieces of a program work, it is less prone to errors due to programmer mistake. In order to implement this form of testing known as “unit testing”, it is necessary to use functions. Let’s look at how to fix up the above code with a function.
To implement a function, we need to extract the code we would like to put into the function from what we have. A good option for the above code would be the following:
function makeOutputString(itemName, number) do
string plural = (number != 1 ? “s” : “”)
return “You have ” + number + “ ” + itemName + plural + “ in your inventory.”
end
The variables “itemName” and “number” are the arguments, or inputs, to the function. The keyword “return” tells us what the function outputs. Hence, this function takes the name of our item and the count of our item and gives us our output string. How convenient!
With that function we defined, we could simplify our code to something like the following:
fruitCounts = {
apple: 3,
pear: 2,
banana: 10
}
while true do
string input = getInput()
if input is in fruitCounts do
print(makeOutputString(input, fruitCounts[input]))
else
print(“You have no “ + input + “s.”)
end
end
Not only does this simplify the code, it makes editing and testing the code very simple as well.
I know this has been a short post, but I hope you’ve learned a thing or two about functions today. Try using them the next time you program and notice how much more readable and organized your code becomes!
have seen it time and time and again. A novice programmer sits down at the computer with the goal of writing the next big computer application. However, they do not have much experience putting code to screen and end up writing an ever-expanding network of while loops and if statements akin to a maze of paths through an unkempt garden. If one wanted to implement a gazebo in such a garden, they would surely have to rewrite much of the logic. If you have ever found yourself writing code like this, fear not. In this post, I will explain how you can use functional programming concepts to more effectively organize your code.
Functional programming? What’s that?
When you wrote that maze of loops and if statements, you wrote in a style known as imperative programming. In imperative programming, operations are executed line by line, and each operation modifies the state of your program (your variables) in some way. To contrast this, functional programming revolves around the concept of functions, which are discrete chunks of instructions that can be reused throughout a program. You might have heard of these before but never bothered to learn how they work. However, you should consider them to be an indispensable tool in your programming arsenal. Functions mitigate a number of problems, such as the existence of duplicate code and the inability to test particular features of the code. Most importantly, functions in functional programming do not modify global state—they merely run a sequence of instructions on an input and produce an output. Even when interspersed with imperative code, functions present a powerful utility for the betterment of your code.
What’s wrong with duplicate code?
You might be perfectly comfortable with writing the same code in multiple places if it gets the job done. However, this is not a good way to program, and there’s a very simple argument why. Say you’re writing a program that appends the same string to an input in multiple places. For example, your program could be keeping an inventory of the various things you have stored away. The user inputs something such as “apples”, and the program will print “You have 2 apples.” A naive way to implement this would be the following:
string haveText = “You have”
int apples = 3
int pears = 2
int bananas = 10
while true do
string input = getInput()
if input == “apple” do
string plural = (apples != 1 ? “s” : “”)
print(haveString + “ “ + apples + “ “ + input + plural)
else if input == “pear” do
string plural = (pears != 1 ? “s” : “”)
print(haveString + “ “ + pears + “ “ + input + plural)
else if input == “banana” do
string plural = (bananas != 1 ? “s” : “”)
print(haveString + “ “ + bananas + “ “ + input + plural)
else
print(“You have no “ + input + “s.”)
end
end
The problem with this code is that we perform the same operation (haveString + “ “ + something + “ “ + input) three times. This becomes a lot to manage. For instance, say you wanted to change the output to something of the form “There are 3 apples in your inventory”. You would have to update the code in three locations in order to implement this change.
How does not having functions affect testing?
Testing one’s code is a great way to make sure it does what it is expected to do and does not contain any bugs. In a purely imperative programming approach, you would have to start your application and test it manually in order to make sure your code works. While this might work fine for a small program, in larger programs, it is often preferable to automatically test parts of the code rigorously in order to make sure those individual pieces work. If the individual pieces of a program work, it is less prone to errors due to programmer mistake. In order to implement this form of testing known as “unit testing”, it is necessary to use functions. Let’s look at how to fix up the above code with a function.
Using functions
To implement a function, we need to extract the code we would like to put into the function from what we have. A good option for the above code would be the following:
function makeOutputString(itemName, number) do
string plural = (number != 1 ? “s” : “”)
return “You have ” + number + “ ” + itemName + plural + “ in your inventory.”
end
The variables “itemName” and “number” are the arguments, or inputs, to the function. The keyword “return” tells us what the function outputs. Hence, this function takes the name of our item and the count of our item and gives us our output string. How convenient!
With that function we defined, we could simplify our code to something like the following:
fruitCounts = {
apple: 3,
pear: 2,
banana: 10
}
while true do
string input = getInput()
if input is in fruitCounts do
print(makeOutputString(input, fruitCounts[input]))
else
print(“You have no “ + input + “s.”)
end
end
Not only does this simplify the code, it makes editing and testing the code very simple as well.
Wrapping up
I know this has been a short post, but I hope you’ve learned a thing or two about functions today. Try using them the next time you program and notice how much more readable and organized your code becomes!
Comments
Post a Comment