Right Tool for the Job? Yeah, Right

Frankly, I’m a bit tired of hearing the hammer and nails metaphor and “right tool for the job” from developers when they talk about programming languages. While there’s nothing wrong with selecting the right tool when there clearly is one, I think the phrase is often misused and seems to be a cheap explanation to justify personal preferences and subjective decisions seemingly objectively. I think when that phrase is uttered, it mostly means something like: the right tool for me (or my company) at that particular time, considering my (our) experience, knowledge, skills and preferences at that time.

Most of the times there are always several “right tools” that are probably equally good “for the job” and the reasons for choosing one over another are usually not merely technical in nature but depend on many other variables from the larger context in which the choice is made. Actually, I don’t even think there’s ever a completely right choice. The complexity of the real world makes it impossible to know for sure, but nevertheless, choices must be made and we approximate. If someone else made a different choice in a similar situation that doesn’t mean it was the wrong tool for the job.

A programming language is not really just a tool anyway. In some ways it is, but the hammer analogy sucks. For building a house you might need hundreds of different tools, tens at the least. For building a large application you could get away with just one language without ending up with bad abstractions. If you count HTML, JavaScript, SQL in typical web apps for example, then maybe you need five or so, but if these are cases of selecting the right tool then they have long become common sense and are not interesting to discuss.

But usually you only need one general purpose language. There are of course some differences between them and some languages have grown into certain roles (forgive me some sweeping generalizations): C++ is for performance and hardware access; Java is for applications and information systems; PHP, Python, Ruby for web apps and scripting etc. (as a side note, I think Scala can play both of the latter roles) In some cases you might perhaps want two of them — programs in higher level languages sometimes “drop down” to C++ for performance, Grails mixes Groovy and Java — or maybe even three, but much more than that would be overkill. Note that I am not at all against the polyglot programming meme, but I do think the choice languages for any given project or organization should be limited to a few.

So programming languages are like tools in the sense that choosing a language somewhat limits what you can do with it. But actually, I would say that a general purpose programming language together with it’s libraries is more like a complete tool set than a single tool. You can choose any tool set you like, each will get the job done. One set might be missing a hammer, another might be missing a saw — if that turns out to be a problem for a few situations then you compensate. Perhaps by renting a specific tool for just the time when you need it, deciding on using two tool sets from the start, dropping a requirement, or finding a workaround that is doable with your current tools. Even if you have to do the latter, it still doesn’t mean you are looking for nails where there aren’t any — it might be a valid choice considering your constraints. However, if this keeps happening then you probably have chosen the wrong tool (or someone chose it before you).

But besides being a tool set, a programming language also forms an important base for communication between developers, just like natural language does. With this comes a whole new set of considerations for choosing a language that have nothing to do with how exactly it fits to solving a problem technically. It also determines what kind of community you have access to, what kind of cultural values you may be indirectly associated with, how many “compatible” developers there are in your area etc. And I think sometimes, but not always, these questions may be more important than the technical ones.

(functions == objects) => awesome!

One thing I increasingly love about Scala is this: functions are objects, and for many common objects it is true that objects are functions as well. Some examples are arrays, lists, maps etc. For example, lets say we have a map from numeric characters to English words corresponding to these numbers:

val n2s = Map(
      '0' -> "zero",
      '1' -> "one",
      '2' -> "two",
      '3' -> "three",
      '4' -> "four",
      '5' -> "five",
      '6' -> "six",
      '7' -> "seven",
      '8' -> "eight",
      '9' -> "nine")

This map moonlights as (okay, okay, “inherits from”) a function of the type (Char => String) and you can pass it where such a function is expected as parameter, like here:

n.toString.map(n2s).mkString(" ")

Quick explanation for those new to Scala:

  • n.toString converts n to its String representation
  • a String is also a Seq[Char] in Scala land, and the map method applies a function of Char => B (where B is any type) to each element in the sequence, thus producing a new Seq[B]
  • we pass our map n2s to this function, which means we will map the Seq[Char] to a Seq[String]
  • that sequence is then turned into a single String using mkString (and specifying space as the separator between elements)

This function is just an example, it probably isn’t actually useful for anything. I just saw something like it in Python and thought I’d try to make the same program in Scala before realizing that it didn’t do anything really interesting (like converting 123 into “one hundred twenty-three” instead of “one two three”).

Another awesome thing about functions in Scala are partial functions, which are functions taking a single argument that are defined only for some argument values (the domain of the function). Map is also a partial function — defined only for the keys it contains — and pattern matching, which is a very important part of Scala, is related to partial functions as well. I won’t go into more detail in this post, but Doug Pardee has written a more in-depth article about functions in Scala.