Language paralysis

It’s winter break which means that I have a good amount of free time on my hands. Though I’m all in favor of sitting around and doing nothing, I do get bored after a few days of that and tend to look for something to keep my mind occupied. I decided that this time I would sit down and learn a new programming language, something I’ve been wanting to do for a while. But the thing is I can’t make up my mind as to which one.

I’ve considered learning one of three languages, each of which is a powerful yet somewhat quirky and niche language. My choices are Common Lisp, Scheme or Haskell. Common Lisp and Scheme are both Lisp dialects, but with different purposes and hence a different feel. From what I’ve learned Common Lisp is a full-fledged industrial strength, general purpose programming language while Scheme has a thriving research community surrounding it and is a great test-bed for implementing programming-language related ideas. Both share Lisp’s defining characteristics such as powerful dynamism and macro facilities. Both are inherently functional languages but are also capable of playing host to other programming paradigms (Common Lisp in particular with its Common Lisp Object System).

Haskell on the other hand is quickly becoming one of the most powerful programming languages on the planet and may be coming close to threatening Lisp’s throne. It’s a purely functional programming language with an increasingly powerful and capable type-system. It’s an excellent tool for language and type-system related research thanks to great parsing facilities and it seems to me that Haskell is at the forefront of computer science research today. Haskell doesn’t have a macro system, but I’ve never heard that be an issue.

All my choices are powerful languages with strong communities, but I simply can’t make up my mind as to which one to learn. I admire all of them and can see the strengths of each, but neither one is really compelling enough for me to sit down and decide to learn it. It’s time to explore some of the reasons behind my current paralysis and see if I can figure out a solution.

Looking back on my history of learning programming languages all the ones I’ve learned to any depth have been motivated by external cause. I learned Java because it was used in my basic CS courses. I learned C++ because I used it in my software engineering class. I learned C for operating systems and digital circuits courses. I learned Python because we use it for most of our research code at school (and it’s become the language I’m most familiar with). I’ve also picked up some JavaScript because I wanted to use it to give some dynamism to my website.

Unfortunately I don’t have similar motivations to help me make my current decisions. My current research is being done in Ruby because of it’s flexible object system. I have some ideas for a side project to pursue next semester but it’s not likely to be something requiring Lisp or Haskell’s particular talents. I’m not going to be doing any research into languages or type systems until the summer at least (and maybe not until later this year). As of this moment, I have zero external motivation to pick and learn any of these languages.

The thing is I really do want to learn one (and eventually all) of these languages. I think it’s a good idea for programmers to be continually learning new languages and expanding the ways in which we can think of our problems. However, I’m coming to realize that simply sitting down and going through a tutorial isn’t enough, at least not for me. I need an actual problem that I intend to solve in the given language. It doesn’t have to be anything fancy, but it should be something that gives me a well-rounded view of the language and it’s capabilities (especially when the language is Lisp or Haskell).

I consider myself a language buff. But it’s one thing to say that I’m interested and read about them and another to sit down, learn them and write code in them. Right now, I’m very interested in learning about Common Lisp, Scheme and Haskell and read both blogs and papers about them. But I can’t take that interest and use it to bridge the gap to learning and using them. Motivation has always been a bit of a problem for me and I’m rather annoyed that it’s preventing me from learning what I want to.

Since I still have about two and a half weeks of vacation left I’m going to give some serious thought as to what sort of programs I want to write in the near future and how I can choose the language that is most beneficial along those lines. At this point I’m open to suggestions for Lisp/Haskell projects that would be interesting as well as hearing about how other people motivate themselves to learn languages that they aren’t actively using.

It’s a great time to be a language buff

I make no secret of the fact that I have a very strong interest in programming languages. So I was naturally very interested when news of the Go Programming Language hit the intertubes. Go is an interesting language. It pulls together some very powerful features with a familiar, but clean syntax and has lightning fast compile times. It certainly takes a place on my to-learn list along with Haskell and Scala. But even as Go becomes the latest hot piece of language news, it dawned on me that over the past few years we’ve seen a slew of interesting languages offering compelling alternatives to the industry “mainstream”.

I guess it all started with the rise of scripting languages like Python, PHP, Ruby and the poster boy of scripting: Perl. Personally, these languages with their dynamic typing, “batteries included” design and interesting syntax provided a breath of fresh air from the likes of C++ and Java. Not that C++ and Java are necessarily bad languages, but they aren’t the most interesting of modern languages. In the early years of this decade computers were just getting fast enough to write large scale software in scripting languages. Things have changed a lot since then.

Dynamic languages aren’t just reserved for small scripts. Software like Ruby on Rails has proved that you can write really robust back end infrastructure with them. The languages for their part have kept on growing, adding features and making changes that keep them interesting and downright fun to use. Python 3.0 was a brave decision to make a break from backwards compatibility in order to do interesting things and it goes to show that these languages are far from ossifying or degrading.

Then there is JavaScript which was supposed to die a slow death by attrition as web programmers moved to Flash or Silverlight. But we all know that didn’t happen. JavaScript has stayed in the background since the rise of Netscape, but it’s only recently with advances in browser technology and growing standards support that it has really come into its own. I’ve only played with it a little, but it’s a fun little language which makes me feel a lot of the same emotions I felt when discovering Python for the first time. Thanks to efforts like Rhino, you can even use JavaScript on the client side for non-web related programming.

Of course, if you want to do really interesting things with these languages, then performance is not optional. Within the last year or two there’s been a strong push in both academia and industry to find ways to make these languages faster and safer. Google in particular seems to be in the thick of it. Chrome’s V8 JavaScript engine is probably the fastest client side JavaScript environment and their still experimental Unladen Swallow project has already made headway in improving Python performance. V8 has already enabled some amazing projects and I’m waiting to see what Unladen Swallow will do.

While we’re on the topic of performance, mentioning the Java Virtual Machine is  a must. The language itself seems to have fallen from grace lately, but the JVM is home to some of the most powerful compiler technology on the planet. It’s no wonder then that the JVM has become the target for a bunch of interesting languages. There are the ports of popular languages — JRuby, Jython and Rhino. But the more interesting ones are the JVM-centric ones. Scala is really interesting in that it was born of an academic research project but is becoming the strongest contender to Java’s position of premier JVM language. Clojure is another language that I don’t think many people saw coming. It brings the power of LISP to a modern JVM unleashing a wide range of possibilities. It has it’s detractors, but it’s certainly done a fair bit to make Lisp a well known name again.

Academia has always been a hot bed when it comes to language design. It’s produced wonders like Lisp and Prolog and is making waves again with creations like Haskell (whose goal is ostensibly to avoid popularity at all costs) and the ML group of languages. These powerful functional languages with wonderful type inference are a language aficionado’s dream come true in many ways and they still have years of innovation ahead of them.

Almost as a corollary to the theoretically grounded functional languages, systems languages have been getting some love too. D and now Go are both languages that acknowledge that C and C++ have both had their heyday and it’s time to realize that systems programming does not have to be synonymous with bit twiddling. D has gotten some flak recently for not evolving very cleanly over the last few years, but something is better than nothing. Also a real shift towards eliminating manual memory management is a welcome addition.

As someone who intends to seriously study language design and the related concepts in the years to come, it’s a really great time to be in getting involved in learning about languages. At the moment I’m trying to teach myself Common Lisp and I have a Scala book sitting on the shelf too. One fo these days, I plan on sitting down and making a little toy language to get used to the idea of creating a language. Till then, it’s going to be really interesting just watching how things work out in an increasingly multilingual world.

Switch-case statement in Python revisited

This post is part of the Powerful Python series where I talk about features of the Python language that make the programmer’s job easier. The Powerful Python page contains links to more articles as well as a list of future articles.

About nine months ago I wrote a post talking about how you might go about implementing a switch case statement in the Python programming language. Python lacks a native switch-case like construct, but there are multiple ways to fake a similar effect. The most naive way would be multiple if-else blocks. A more Pythonic way would be to use Python’s dictionaries and and first class functions. A simple example in C, and the two Python ways is shown below.

switch(n) {
  case 0:
    printf("You typed zero.\n");
    break;
  case 1:
  case 9:
    printf("n is a perfect square\n");
    break;
  case 2:
    printf("n is an even number\n");
  case 3:
  case 5:
  case 7:
    printf("n is a prime number\n");
    break;
  case 4:
    printf("n is a perfect square\n");
  case 6:
  case 8:
    printf("n is an even number\n");
    break;
  default:
    printf("Only single-digit numbers are allowed\n");
  break;
}

if n == 0:
    print "You typed zero.\n"
elif n== 1 or n == 9 or n == 4:
    print "n is a perfect square\n"
elif n == 2:
    print "n is an even number\n"
elif  n== 3 or n == 5 or n == 7:
    print "n is a prime number\n"

options = {0 : zero,
                1 : sqr,
                4 : sqr,
                9 : sqr,
                2 : even,
                3 : prime,
                5 : prime,
                7 : prime,
}

def zero():
    print "You typed zero.\n"

def sqr():
    print "n is a perfect square\n"

def even():
    print "n is an even number\n"

def prime():
    print "n is a prime number\n"

The Fine Print

However, as the comments in the original post show, neither of the Python examples are a very good solution. They lack the versatility and power of the original C form, both in terms of syntax and semantics. Syntactically, neither of the forms do a good job of conveying the intent of the written code. The if-else form does an acceptable job and may be fewer lines, but it clutters the code with keywords and multiple equality checks and boolean combinations. The dictionary form is even worse at conveying the intention of the code.

Semantically, the two forms don’t stand up to the C form either. Multiple if-elses are probably as close as you can get, but it doesn’t work quite the same way. In particular, the ‘fall through’ semantics of a switch-case statement, where consecutive blocks are executed if there is no break statement, is a bit clumsy to duplicate. Repetitive code is almost always bad and trying to mimic the semantics of switch-cases for non-simple examples (including the above one) inevitably requires some repetition. Using dictionaries is simply a semantic mess. Creating a list and coming up with function names is really too much trouble for the simple task at hand. List comprehensions and dictionary comprehensions are powerful tools, but they simply have no place in something like a switch-case statement.

The Real Problem

This is one of the cases (pun unintended) where though you can use existing language features to get what you want (or something close), you would really like to have in-built language support. Python is a pretty well designed language as far as languages go, but it has it’s share of quirks. Personally I don’t consider a lack of switch case a particularly damaging lack, though there have been times where I wished there was one. In fact, a little Googling shows that there was a Python Enhancement Proposal submitted a few years ago but it was rejected due to lack of popular support.

There is an excellent Stack Overflow question on what the switch/case substitutes are and how to choose between them. The first answer to that question captures the essence of the problem at hand. It’s not a matter of how the alternative should be implemented, but rather what the alternative should mean. The if-else and dictionary lookups are generally useful if you have a simple choice to make in code which is mainly procedural. However if your code base is very object oriented, then you are probably better off with something like polymorphism to choose between alternatives. The solution should fit the problem, not the other way around.

The final thing I would like to say on this matter doesn’t involve Python at all. Rather it’s about Common Lisp, which I’ve been teaching myself for the last few weeks. The Lisp family of languages is particular famous (or infamous, depending on your point of view) because of the general lack of concrete syntax. Lisp code is written directly in the form of S-expressions. Essentially you write out the abstract syntax tree that in other languages is generated by the parsing the source code. Because the programmer has access to this representation, it’s possible to write code that will generate these S-expressions at compile time. In essence, this allows Lisp to be a programmable programming language. This is important because you as the programmer can basically add your own extensions to the language without waiting for a committee or community to approve it. In our case, if Common Lisp didn’t come with a switch-case statement and you really needed one, you could roll your own. In fact, it has been done. That’s not to say that rolling your language features is easy or something you should do on a daily basis, but in languages that allow it, it can be a very powerful tool if used right.

To be fair, I think you could write code to generate code in any run it in any language that has text processing and dynamic loading, but it would probably be very tedious and error-prone. The Lisp S-expression form lets you do it a much more elegant and powerful fashion.

In Conclusion

While Python does not have a switch case statement (and will probably never have one) there are a lot of other language features you can use to get the job done. It’s important to remember that you shouldn’t just be trying to recreate the semantics of switch-case (as that can be very messy). As the original post shows, trying to clone the C implementation is a futile endeavor. You need to pay attention to what the problem really is and then pick a Python feature that solves the problem correctly and elegantly. And if you get the chance, do explore languages like Lisp where syntax is fluid. It will help you better understand the difference between what your code looks like it’s doing and what it actually is doing. Happy hacking.