What’s the Point, Polyglot?

11 Jan 2012

Perfection at a programming language is a nebulous concept at best. One can certainly excel at a language, knowing how to write beautiful and effective code, but those in use are moving targets. As with their spoken counterparts, computer languages evolve by the people who use them.

Even if reaching the paragon of a language were attainable, there are many other reasons to broaden one’s horizons.

Brass Tacks

Pragmatically, learning a new language may simply let you play with the neat library that does X, Y and Z, and with flair. How many people learned JavaScript to do cool things with jQuery, Tcl to write IRC bot Eggdrop scripts, or Lua to hack GTA: San Andreas? Applications on your futuristic mobile device are likely to be written in Objective-C or Java; if you want to build something for it, you probably have to learn one of those.

Socially, learning a new language may open doors to a new ecosystem of developers, academics, communities, meetup groups, functional alcoholics, and hey, even job opportunities. For those of us who win our bread one byte at a time, these are reasons enough.

But maybe there’s no Clojure library that piques your interest, any Erlang developers that you want to hang out with, or Perl jobs you care for. What now?

Beauty is More than Syntax-Deep

Syntax may be the most obvious differentiator between two given languages. Does this language require semi-colons? Is whitespace significant? How does one declare functions or assign variables?

Digging deeper, many languages have syntactical sugar, special constructs or idioms built into the language to perform a common or useful task. It may be as simple as being able to increment-and-assign via foo += bar rather than foo = foo + bar, or as seemingly trivial as declaring dictionary/hashes with literal notation:

fooMap = {"bar": "baz"}

Compare the above to:

std::map<std::string,std::string> fooMap;
fooMap["bar"] = "baz";

Even the presence of a hash table literal, i.e. curly braces with key-value pairs, can be telling of the language’s choices. The former, more concise way can be seen in Python or JavaScript. The latter, more verbose example is from C++, whose standard library (but not the language itself) provides a map data structure, but no literal.

In modern computing where processor cycles are cheap and memory is plentiful, data structures like hash tables are often part of the “batteries included” toted by many languages.

Eliminating the need to give a second thought to how hash tables work means never opening up the key-in, value-out black box to find a self-balancing red-black tree. One can use array.sort() a thousand times and remain forever oblivious to CPython’s impressive underlying algorithm, Timsort.

Some languages take care of the plumbing so to optimize for architecting beautiful buildings, but perhaps unbeknownest to the Frank Lloyd Wrights of the world, there are difficult and great problems to be solved in the pipes.

A Functional Example

Python list comprehensions are not only a powerful shorthand for manipulating lists, but a sneaky way of learning some functional programming concepts.

Take this straightforward example of culling fruits from a grocery list and, since they are so very important, we’ll generate the list in uppercase:

groceries = ["bacon", "bread", "apple"]
fruits = []
for item in groceries:
    if item == 'apple' or item == 'orange':
        fruits.append(item.upper())
print fruits
# ["APPLE"]

With list comprehension, the above can be rewritten as:

groceries = ["bacon", "bread", "apple"]
fruits = [item.upper()
          for item in groceries
          if item == 'apple' or item == 'orange']
print fruits
# ["APPLE"]

At the core is for item in groceries, which iterates through each item in the grocery list. Next, the if conditional filters and selects fruits from the list. Finally, item.upper() maps and transforms all fruits into uppercase.

In earlier versions of Python, actual functions called map() and filter() were used, but have since been deprecated in favor of list comprehensions.

Meanwhile, in Ruby:

groceries = ["bacon", "bread", "apple"]
fruits = groceries.
  select {|x| x == 'apple' || x == 'orange' }.
  map {|x| x.upcase }
p fruits
# ["APPLES']

Granted, these may be very elementary examples of functional techniques, but illustrate that a language can introduce or facilitate particular methods of problem-solving.

For You, For the Computer

The path we trace from human thought to computer execution is a complex one. Languages are but a tool to accomplish this in a way we can comprehend as individuals, but also with each other in collaboration. Exploring different paths means sharing the accomplishments of fellow travelers, learning new routes, and perhaps, even finding your own. ■