Re: Should function argument be changed in function body?



scs@xxxxxxxxxx (Steve Summit) writes:

> Tim Rentsch writes:
> > There doesn't seem to be much upside to allowing function parameters
> > to be modified; conversely, following a guideline that function
> > parameters not be modified has relatively low costs and fairly
> > clear benefits.
>
> Can you name some of those benefits? They're not clear to me.

Sure. In a previous post I listed some specific cases where it's
useful to have the initial value available (quoting):

showing the value with printf for some tracing
writing an assertion relating the function's output and input
viewing the value while debugging

All of these uses (not to mention some others) tend to show up
later in the development cycle as much as they do earlier when
the code is first written. It often isn't possible to
anticipate on first writing when the original value will
subsequently be needed.

[End of quoting.]

There's also a different kind of benefit having to do with
comprehensibility. For example, in long functions, it's
usually better to initialize a loop variable right before
the loop: because the initialization is right there, it's
easy to see what it is, and know that the variable hasn't
been inadvertently set to the wrong thing. We can't do
that with a parameter -- it had to be initialized at the
beginning. Compare

t = n*3 + 7;

...

while( t-- ){
...
}

with

for( t = n*3 + 7; t--; ){
...
}

The second is better (I claim), because everything we
have to read for the loop is right there at the loop.
We don't always have this choice if parameters are used
in loops, because of how they are initialized.

Another example of a comprehensibility benefit is where
on the spectrum of imperative vs functional a piece of
code is. The more there is state that changes, and the
less there is state that doesn't change, generally the
harder we have to work to understand a given piece of
code. For example, compare

size_t
length_of_string( const char *s ){
size_t n = 0;

while( *s ) s++, n++;
return n;
}

with

size_t
length_of_string( const char *s ){
size_t n = 0;

while( s[n] ) n++;
return n;
}

I admit the difference between these functions isn't very big,
and in a code review I'd probably be ok with either one. But
the second one is a little easier to understand. I can see at a
glance that 'n' holds the index of the first null character in
the string 's'. Of course, I can see that in the first function
also, but there's a little more mental effort involved. You
see what I mean?

Summarizing the two examples above: a benefit of keeping
parameters unchanged is that it allows or encourages other
good development practices.


> (I agree that modifying function parameters is not something
> you'd want to do every day, but sometimes it's convenient -- more
> so that introducing a local variable to hold a modifiable copy --
> and I don't understand the predilection in some circles for
> mandating that parameters not be modified.)

I expect we're not really that far apart on this. Let me offer
an analogy. Usually it's better for (non-const) variables to be
initialized subsequent to their declaration. Not always better,
not hugely better, but usually better. Every so often I am
tempted to "break the rule" and write initializing declarations.
When I give in to that temptation, probably 999 times out of
1000 everything works out fine. But every now and then I get
bitten by it. That's the thing: when I break the rule,
sometimes I get bitten; but when I follow the rule, I never do.

I suspect people who are strong advocates of never modifying
parameters do so largely for that reason - if one follows the
rule, one never gets bitten.

So if you want to make exceptions now and then, that's ok, just
be sure you bring your venom kit with you. :)

.



Relevant Pages

  • Re: ccs compiler with pic12ce674?
    ... I modified the program to only toggle pin 5. ... You don't initialize it to ... > directive probably set it to 0 and nothing in your loop gets executed. ... > toggleState to TRUE so GP4 gets set high the first time through. ...
    (comp.arch.embedded)
  • Re: ATL OOM Resource leaks, and inconsistent behavior?
    ... I had the call to initialize the redemption object at the ... the initialization code so that it no longer initializes in any loop. ... >> You need the extra AddRef(). ...
    (microsoft.public.win32.programmer.messaging)
  • Re: New style DO syntax?
    ... FOR initialize THEN successor WHILE ... at the beginning of the loop so it shouldn't be there. ... The question is not what Universal Iteration Construct ...
    (comp.lang.fortran)
  • Re: ccs compiler with pic12ce674?
    ... I'm not surprise that you see MCLR high. ... You don't initialize it to anything ... directive probably set it to 0 and nothing in your loop gets executed. ... GP4 to 1 before entering the loop and see if it goes low the first time ...
    (comp.arch.embedded)
  • Re: const pointer
    ... const char ch; ... "const", on the ... So the phrase "definition statement" is incorrec. ... The term "initialize" can be used informally to refer to assigning ...
    (comp.lang.c)