I often find it hard to decide and am inconsistent. Are there some rules I could follow?
For example:
def remove_except(haystack, needle, exclude_value):
for key in hackstack:
if key in needle and haystack[key] != exclude_value:
hackstack.pop(key)
could easily be:
def remove_except(needle, exclude_value, haystack):
for key in hackstack:
if key in needle and haystack[key] != exclude_value:
hackstack.pop(key)
Not a perfect example because I tend to put the variable being modified as the first parameter, e.g. haystack, and that might even be a convention but apart from that I'm unsure what to do.
I'm interested for more languages than just Python.
Argument Order MattersThe order or arguments supplied to a function matters.
A function is defined as a relation between a set of inputs having one output each. In simple words, a function is a relationship between inputs where each input is related to exactly one output.
3. Positional Arguments. During a function call, values passed through arguments should be in the order of parameters in the function definition. This is called positional arguments.
Parameters are specified within the pair of parentheses in the function definition, separated by commas. When we call the function, we supply the values in the same way.
The only rule is be consistent. That doesn't only mean be consistent between and within the APIs you define, but also be consistent with any APIs commonly used in the environment. Note that this may mean you do things differently in one environment than in another. Try to fit in.
Now, with Python and JavaScript, you can use object orientation to take at least the haystack out of the question, because the haystack will be (or at least, can be) an object you're acting on and so how you do that will be dictated by the language (e.g., delete haystack[needle];
[JavaScript for removing a property from an object] or del haystack[needle]
[Python for removing a dictionary entry]). C isn't object-oriented (C++, D, Objective-C, and several other derivatives are) and so you'll need to look for the convention there.
Subjectively speaking, in my experience, the haystack
normally comes first, but that may just be my experience. Similarly, my subjective opinion would be that the exclude_value
would be the last thing (so, haystack
, needle
, exclude_value
) because there would be other operations that would take haystack
, needle
, something_else
— but that's just an opinion.
I believe the convention is, left to right, most vital to least vital. so for your example I would do (needle, haystack, exclude_value). needle is the most vital in this case because its the defining info of the call. the same haystack could be used in another call with a different needle. Exclude_value seems like it could be optional.
It is very much up to you. If you are writing a single function that is unlike anything else in the containing, say, project then required/important parameters go first and optional/unimportant trail after. The language you are using may influence choices; Python allows optional named parameters or keyword arguments to be supplied but they have to follow positional parameters.
If you are writing a set of similar functions for an API then consistency becomes more important. Using the haystack example, you might have
def insert(haystack, needle)
def remove(haystack, needle)
def remove_except(haystack, needle, exclude_value)
def copy(haystack, haystack2)
where haystack goes first because it is the key parameter for all the listed methods and having
def remove(needle, haystack)
def remove_except(haystack, needle, exclude_value)
would look odd (but of course would still work).
If you using an object-oriented language and you find yourself writing a whole slew of functions that share a parameter, you probably consider making that an object and the functions methods that operate on that object but that's probably outside the scope of the question.
For the language of your choice, find some well-used code and study it. If you are using Python, take a look in the standard libraries. For Javascript, jQuery might be good.
Just as some supporting info for the chorus of "put the haystack first", in this case mostly for JavaScript: when you're thinking about which parameter is the "most important", or which is the "haystack", it (can) help to think about which parameter is likely to be different between invocations, and which is likely to change. In your example, the "needle" is probably pretty volatile from invocation to invocation, while the "haystack" may always, or almost always, be the same thing.
Well if that's the case — that it's common to use a utility like that for just one particular object — the "bind()" method available in new JavaScript environments (on the Function prototype), or added by a library like Prototype or Functional, can be really useful:
function whatever(haystack, needle) {
// ...
};
var myHaystack = new Haystack( /* ... */ );
var myHaystackWhatever = whatever.bind(null, myHaystack);
Now the function "myHaystackWhatever" can be used like this:
var result = myHaystackWhatever(someNeedle);
That may seem trivial, but in a functional language like JavaScript the ability to easily and reliably create a new function as a variation on an existing one is super handy, saving a lot of typing and paren/brace matching messiness.
The point here is that facilities like "bind", especially in JavaScript which has purely order-based binding of invocation values to formal parameters, you bind in fixed values from left to right. Thus, if your left-most parameter is the one most likely to be a zillion different things, then "bind()" isn't too interesting. (The Functional JavaScript library has a way of binding other parameters and not just left-to-right, but it's pretty exotic and weird and, in my opinion, mostly interesting as a coding example.)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With