Categories
Programming

This is not an argument

It’s interesting to look at how various languages deal with passing arguments to functions. It’s a bread-and-butter part of programming, and if you come from a C background it’s surprising to realise that there’s better ways of doing it.

A simple function call in C looks something like this:

print_string(“hello”);

A more realistic example looks like:

gtk_box_pack_start(box, my_button, false, true, 10);

Firstly, let’s look at this from the point of view of someone writing the code originally. You would most likely have to consult the API documents to remember what the arguments are, and what order they come in. You might do this by switching to your browser, clicking several times to find the right page and then reading. If you have integrated API documentation, it’s probably just a keypress away. Or, maybe you have tooltips which mean that the information is immediately available as soon as you type the function name. Once you know what the order of the arguments, you just type the relevant variable names or literals and you’re done. The C language allows very concise function calls.

Let’s look at this from the point of view of a code maintainer, since software professionals spend most of their time working with existing code. Maybe you are reading the code and you want to know what do the arguments do. Maybe you think that the “false, true” is the wrong way around? Again, you would consult API documentation to find out what the formal parameters are. If you’re using good tools you only need to hover your mouse over the code to find out what the function prototype is. But even that isn’t so hot! Tooltips show the function prototype in a little popup window, and you have to mentally line up the arguments with the prototype and think “So, that ‘true’ is the ‘expand’ argument, and the ‘false’ is the ‘fill’ argument”. A better tool would annotate the source itself with the names and type information from the function prototype. You would just hover your mouse over the function call and it would temporarily rearrange the visual presentation to efficiently present all the information at a glance.

Bad C! The language is making my life as a software developer hard. However, I’ve said before that we shouldn’t consider individual parts of the programming system in isolation – we need to consider the whole kaboodle. In this case, you can see that integrated API documentation or nice visual presentation tools would provide relevant information to the programmer, even though the language itself isn’t much help.

The C school of thought – “identify arguments by their position in a list” – is only one way to do it. Let’s look at two other languages (smalltalk and ocaml), and see how they do argument passing.

In Smalltalk, method names (aka selectors) look something like this:

open:forWrite:

And to call that method (on object foo) you say:

myfile open: “test.txt” forWrite: true

.. which opens a file for writing. This style of coding is more “self-documenting” than the equivalent in C. Reading code becomes much easier, since the names of the parameters are written down each time. If we return to the gtk_box_pack example from earlier, it’d look something like this in smalltalk:

mybox packStart: my_button
withExpand: false
withFill: true
withPadding: 10

In ocaml, we have can use optional “labels” to annotate function calls. So, without labels the same call in ocaml could look like this:

gtk_box_pack_start box my_button false true 10

And with labels we’d have:

gtk_box_pack_start ~box:box ~child:my_button ~expand:false ~fill:true ~padding:10

If you use labels on all arguments then you can enjoy the dizzy heights of “commuting labels mode”, where you can present the arguments in any order:

gtk_box_pack_start ~child:my_button ~padding:10 ~expand:false ~fill:true ~box:box

To a C programmer, the ability to rearrange arguments doesn’t look very exciting. However, ocaml treats functions as first-class objects which can be created on the fly at runtime. So, we could call gtk_box_pack_start at runtime and only bind the ‘expand’ and ‘fill’ arguments. We’d get back a new function which takes just ‘box’ ‘child’ and ‘padding’. This style of programming is very powerful, since it allows you to build your own specialised functions out of more general functions, without doing a lot of bookkeeping. To do the equivalent in C (or any language without closures) you would have to store the partially-known arguments somewhere until you knew the values for all of the arguments.

I’m one of those people who will write a perl script rather than doing a task manually more than once. If you do the task (in this case, “what are these arguments”) hundreds of times every day, then it’s reasonable to make the task as easy as possible. Every time you ask a question when reading code – like “what are these arguments” or “who calls this function” – count the number of keystrokes and mouseclicks which you need to answer the question, and also the number of words
you have to read. In my dream world, every answer would be a single click away.