Introduction

In my day job, among other things, I masquerade as a developer of software. Mostly this pertains to embedded C++, sometimes I debug some Java, and occasionally I work on a Verilog simulation testbench. I used to also do HTML and JavaScript, but that work has been shipped to India.

A few years ago, I was introduced to the programming language Haskell in graduate school. This first occurred through an undergraduate programming languages course that I sat in on, because I had read a bit about Haskell on the web, and my interested was piqued. I was really intrigued! This language required a completely different mindset from the C/C++/Java/Perl world to which I was accustomed! It challenged me to understand problems differently and to describe their solutions in a different way. I was hooked. After this, I continued to learn more through websites, blog posts, and personal experiments. My adventure into Haskell continued with a graduate-level class on programming languages, but that is another post for another time.

Concepts learned from Haskell

Some aspects of Haskell that I fell hard for are the concepts of immutability and referential transparency. The former describes a "thing" that, once created, can't change. This means that you can create an integer variable, say numberOfPeople , initialize it to the value of 5 , and then you are not allowed to modify numberOfPeople anywhere in its scope. The compiler will scream and shout with an error if you do make that mistake.

The other concept, referential transparency, refers to the idea of an expression that yields predictable outputs for all possible inputs, and its output y is always the same for a given input x. Imagine the expression is a black box that implements a mathematical function f such that y = f(x). If the black box is referentially transparent, then you could replace that black box with a purple box that implements f differently (but is still referentially transparent) and never know the difference (except for the superficial change in color). This is a powerful concept that extremely simplifies the problem of understanding a program.

How to survive with C++

Unfortunately, I have since left academia, and my job does not use Haskell or its kind. So, I am forced to make do with C++ and Java. But I simply have not been able to let go those lessons I learned. So, I began to create immutable things and develop referentially transparent code. More and more, I've learned how to apply these two ideas in my everyday approach to programming.

const and immutability

The major visible impact on my code is the use of the const keyword in C and C++. I use it everywhere I possibly can. You might say that I am fanatical about const . I even plan my code, so that I am able to use const as much as makes sense.

So, what is const ? It has many different uses, but in general it means "read-only." const is C/C++'s nod to immutability. To demonstrate the above example in C/C++, you would type:

const int numberOfPeople = 5;

This is probably the simplist use of const , but it is also the one that (I suspect) gets the least usage. This tells me (and the compiler) that numberOfPeople will always equal 5 . In fact, I could replace all uses of numberOfPeople in this scope with 5 . (Sounds like referential transparency? It is!) Of course, I don't want to replace numberOfPeople with its value, because numberOfPeople is more descriptive of its purpose that 5 will ever be. But now I can go on my merry way attempting to understand this piece of code with comfort in the knowledge that numberOfPeople will not accidentally change its value on me.

That last statement is very important. When a software developer is debugging a program (as s/he often is), just knowing that one "thing" will not change after creation decreases the scope of required knowledge for that session by one. If all things are immutable, that significantly reduces the probability that bugs are present in dynamic logic. Thus, by being " const -ipated" with your code (by using const wherever possible), you can kill bugs before they even appear!

As a side note, I recently encountered un- const -ipated code that could have used an extra-strength dose of immutability. That plus variables named with "tmp" being reused for different purposes led to the introduction of several bugs. I hate to say that I'm vindicated for my beliefs, but it felt good to know that I will run into that problem much less often.

Applications of referential transparency

Along with immutability, I strive to develop functions that are referentially transparent. Of course, using an imperative, object-oriented language in the way for which it's designed, most of it is not. However, when the occasion strikes, I go for it.

One case where I think referentially transparent functions are beneficial is if they are private class methods. Too often, I have tried to trace through code in which a member variable is assigned in multiple places. This is difficult to keep track of, especially if you have one function that initializes the variable, then enters a loop with no reference to that variable. Then, with a grep , you discover that the variable is being updated by at least one other private function called in that loop. This effectively hides references and is referentially opaque. By turning that second function into one that takes arguments and returns a result that is assigned to the member variable, it becomes more apparent (or transparent) what is happening.

Another profitable case of referential transparency, combined with immutability, is the use of const as a modifier on a class method, e.g.

class A { /*...*/ int get() const; /*...*/ };

This allows you to use an const instance of A and retrieve any values based on its member variables. The function get() promises not to change any member variables; thus, given an immutable object of type A , get() is referentially transparent. (Of couse, it could modify external values, so it is not necessarily completely referentially transparent.)

Conclusion

So, the moral of the story is that two concepts I picked up from the functional programming language Haskell can be applied to my daily work in C++ (and other languages). I strongly advocate trying this out for yourself. It's funny, but you may not even realize how much time you're saving yourself (or others who look at your code) until you get used to doing it then look at somebody else's un- const -ipated code.

I wrote this post for three reasons that I want to mention.