Daniel Lemire's blog

, 9 min read

Function signature: how do you order parameters?

11 thoughts on “Function signature: how do you order parameters?”

  1. I could be wrong, but I think in C and C++ we pass variable parameters, then const parameters, then optional parameters.

    Some friendly languages allow us to re-order parameters in the call, if we use something like CopyObject(source = s, dest = d, len = l).

    1. I could be wrong, but I think in C and C++ we pass variable parameters, then const parameters, then optional parameters.

      Here is the fwrite function signature: fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);.

      Some friendly languages allow us to re-order parameters in the call, if we use something like CopyObject(source = s, dest = d, len = l).

      As wikipedia points out, it is even possible in C if you pass a struct:

      https://en.wikipedia.org/wiki/Named_parameter

  2. davetweed says:

    Personally, my “trumps everything else” rule is: order parameters in such a way that parameters of the same (or same family, such as uint8_t and uint32_t) are well separated so there’s no tendency to confuse them in a way that still compiles. The classic example of how NOT to do an API is memset: it takes essentially [if you unpick the char & size_t typedefs) (void*, uint8_t, uint32_t) with the second parameter being the one to set the bytes to while the second is the size, but in the wild you still see code that has very clearly got it the wrong way around, yet somehow hasn’t been detected yet. Given that I always follow an “array ptr” immediately by the length, I’d choose to structure memset as (uint8_t valueToSetTo, void* ptr, size_t length).

    1. (…) in the wild you still see code that has very clearly got it the wrong way around, yet somehow hasn’t been detected yet

      Hopefully, people will test their code…

      1. David Tweed says:

        It’s amazing how many bugs testing, particularly testing that’s not zealously nasty trying to break stuff, doesn’t find, such as memsetting to 0 and swapping the args: it won’t directly cause a crash, but might leak security info:

        https://www.redhat.com/archives/rhl-devel-list/2009-November/msg01963.html

  3. Chloe Lewis says:

    `Nobody says “I copied to x the value y“.’

    Though we might say “I made an x with the value of y”, or “I made an x by copying y”.

  4. Jan Mikkelsen says:

    John Lakos specifies something similar in “Large Scale C++” from 1997 – arguments being modified come first in the parameter list. He also specifies they should be pointers so that it is obvious at the calling site they will be modified – this makes them different to the const-references elsewhere. not as fashionable these days but still a convention we follow.

    (Your C++ example should be “type& x”)

  5. Peter Turney says:

    Ideally a good editor would prompt you as you write your code. As soon as you type the function name, it should tell you the expected arguments.

    1. David Tweed says:

      That works on the writing side. The ogher issue is reading call sites (where obviously the variable names may be be based on their complete usage and not just what it means in this function call). I suppose you do a mouseover tooltip.

  6. Chris Matheson says:

    i can’t talk for C / C++ etc, but in JS the order or params can become really important if your trying to use a functional programming approach.

    eg. `copy(from, to) ` may read well, but when using bind because one of those params is “constant” for your program `copyThing = copy.bind(copy, thing);` i would take a lot of time to try and choose the common case and arrange params in the order that it would make sense to bind them.

  7. “More generally, when acting on a data structure, I would argue that the data structure being modified (if any) should be the first parameter.”
    In functional programming that has partial calls and composition, this is the opposite. To build up a more complex operation, you compose functions together, leaving the last argument to be filled by the result of the previous function in the chain. The last thing passed in the thing being acted upon (at least by the first function in the chain), which is often the data structure.

    In an OO world, you’d be correct, though.