Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When I define functions, in what order should I put the parameters?

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.

like image 925
2371 Avatar asked Jan 19 '11 14:01

2371


People also ask

Does the order of parameters in a function matter?

Argument Order MattersThe order or arguments supplied to a function matters.

What is the proper way to define a function?

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.

When calling a function the arguments should be in order?

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.

Where do parameters go in the definition of a function?

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.


4 Answers

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.

like image 76
T.J. Crowder Avatar answered Oct 29 '22 04:10

T.J. Crowder


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.

like image 35
Matt Avatar answered Oct 29 '22 05:10

Matt


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.

like image 1
Spaceghost Avatar answered Oct 29 '22 06:10

Spaceghost


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.)

like image 1
Pointy Avatar answered Oct 29 '22 04:10

Pointy