Comment by Yajirobe

5 years ago

> output arguments are to be avoided in favour of return values

what is an output argument?

An output argument is when you pass an argument to a function, the function makes changes, and after returning you examine the argument you passed to see what happened.

Example: the caller could pass an empty list, and the method adds items to the list.

Why not return the list? Well, maybe the method computes more things than just the list.

  • > Why not return the list? Well, maybe the method computes more things than just the list.

    Or in C you want to allocate the list yourself in a particular way and the method should not concern with doing the allocation itself. And the return value is usually the error status/code since C doesn't have exceptions.

That's a C/C++ trick where a location to dump the output is presented as an argument to the function. This makes functions un-pure and leads to all kind of nastiness such as buffer overruns and such if you are not very careful.

sprintf(buffer,"formatstring", args)

'buffer' is an output argument.

  • It's wrong to call output parameters a "C/C++ trick" because the concept really has nothing to do with C, C++, buffer overruns, purity, or "other nastiness".

    The idea is that the caller tells the function its calling where to store results, rather than returning the results as values.

    For example, Ada and Pascal both have 'out' parameters:

        https://stackoverflow.com/questions/3003480/the-use-of-in-out-in-ada#3004067
    
        https://freepascal.org/docs-html/ref/refsu66.html#x182-20600014.4.3
    
        http://www.ada-auth.org/standards/rm12_w_tc1/html/RM-6-1.html
    

    Theoretically, other than different calling syntax, there's conceptually no difference between "out" parameters and returning values.

    In practice, though, many languages (C, C++, Java, Python, ...) support "out" parameters accidentally by passing references to non-constant objects, and that's where things get ugly.

  • Not only in C land; C# has "ref" (pass by reference, usually implying you want to overwrite it) and "out" (like ref but you _must_ set it in all code paths). Both are a bit of a code smell and you're nearly always better off with tuples.

    Unfortunately in C land for all sorts of important system APIs you have to use output arguments.

An output argument (or parameter) is assigned a result. In Pascal, for instance, a procedure like ReadInteger(n) would assign the result to n. In C (which does not have variable parameters) you need to pass the address of the argument, so the function call is instead ReadInteger(&n). The example function ReadInteger has a side effect so it is therefor preferable to use an output parameter rather than to return a result.