In programming, is it good style to use the same name for function arguments and parameters?

Agreed. It’s difficult to avoid “out” parameters completely, but IMO they should be avoided as much as possible. And make them as side-effect free as possible.

And yes, most likely I’ll use mild abbreviations if they’re clear. Though “temp” gets dangerous since it’s also short for temporary.

A good code editor will have autocomplete. I use it all the time. It saves on the typos, which get caught at compile time anyway.

It’s good practice to not use out parameters and use return values instead as you are already doing. But sometimes a function needs two parameters changed. A swap() function, for example. There are ways around that, though, such as putting the two variables in a returned struct. Passing by reference may be necessary sometimes, but it’s also a good way to introduce bugs and make code harder to read and understand.

One practice we used to indicate the difference between internal variables and passed parameters was to capitalize passed parameters and use lowercase first letter for internal variables. So you could do this:

double getKelvinTemperature (double Temperature)
{
 int temperature=Temperature;
 // Do a bunch of stuff with local temperature 
 // after initializing it with passed-in temperature.
 return temperature;
}

And the code would still be clear. Not that I’m recommending using the same variable name, but it coupd be done.

(btw, thanks for the formatting help)

Whether that convention works for you depends. It’s also common to capitlalize objects and use lowercase for primitives. But if you stick to the uppercase for passed parameters and lowercase for internal variables, you’ll know at a glance which is which.

Depends on the language. If you have some horrible language that won’t nest functions, then use the same name. If you have a language that allows a function to be declared in the same scope as the variables, you should not pass parameters at all. Both make it explicit what you are doing. Ensure the function name makes it clear what you are doing as well. Don’t give it a generic name, name it to exactly capture the fact you are just restructuring, and the function is not intended as a utility.

In general however, this isn’t even a question. A function’s formal parameters are named for local relevance. The actual parameters could be anything. Names of variables and formal parameters can follow all manner of conventions. It is more important that you stick to the chosen one. Choice of then depends on context. I do a lot of scientific numerical stuff in one of my lives. Appending the units to a variable or parameter name can be a life saver.

(Just occurs to me that a IDE that could track units and dimensions through expressions and functions would be a great idea. I wonder if there are add ons that do this already?)

Encapsulation is your friend. Global variables are bad. Functions should not assume the existence of other variables if it can be avoided. If you write a function that doesn’t take parameters but assumes the existence of other in-scope variables, that function can’t be reused elsewhere. And also, debugging will be a pain, and no one can read the function by itself and get a complete picture of what’s going on. Also, unit testing the function will be more difficult.

Also, if you heavily lean on your code editor’s extensibility for readability, the next person to maintain your code is going to have problems unless they’ve installed the same macros and features you are using. It’s better to not create dependencies like that.

Should be part of the language, not the IDE. It’s possible to implement this with templates in C++; I wrote a prototype a while back though I never really fleshed it out. Get the units wrong and you get a compile error.

At least one of your function name or your comment is highly misleading, there.

For example: GitHub - mpusz/mp-units: The quantities and units library for C++

Frankly dimensioned types shouldn’t be primitives anyway. You should have something like:

class Temperature {
public:
  static Temperature ofCelsius(double tempC)...
  static Temperature ofFahrenheit(double tempC)...

  double toCelsius() const;
  double toFahrenheit() const;

...
}

And anything else that takes a number that “means” a temperature of any units should take a Temperature instance instead. Most operations that you can do to a double don’t make sense for a temperature anyway.

Yeah. All this can be enforced with a proper type system. For instance, you can require that units be a perfect square if you take the square root. sqrt(2*energy) gives a compile error, but sqrt(2*energy/mass) is valid.

F# actually builds units into the language. C++ does it with templates. I’m guessing not too many languages are flexible enough to offer this properly, though. Probably Rust.

Sad to say, I had to explain to my students that if the code and the comments don’t agree, the code wins.

Units to any power are perfectly valid, including fractional powers (though you might want to throw a warning for that, because fraction-power units are uncommon enough that they’re most likely not intended). The biggest thing you want to avoid is adding quantities with unlike dimensions (though adding with unlike units but like dimensions, such as 1 meter plus 1 foot, should be allowed).

And it’s easy to say that certain operations don’t make sense with certain dimensions… until they do. For instance, you’d never want to take a sum of two temperatures… unless you then divide the sum by two to find an average.

Oh, and the classic HP 48 calculator included native support of units, and treated them properly. Addition of quantities of like dimension but unlike units gave a result in the second unit, so the standard way to do unit conversions was to add 0 of the second unit (for instance, 1 inch + 0 cm = 2.54 cm).

I’ve also seen a PC calculating environment that did it, I think it was called MathCAD? A college I know of used it in some physics labs.

Oh, and what I’d really like to see would be a language that treated propagation of error correctly. But I never have, probably because it’s hard to even pin down just what correct propagation of error even is. You could assume all errors are Gaussian, and store both a most-likely-value and a sigma for every variable, and that works well enough for addition and multiplication, because those all keep Gaussian errors Gaussian. But it fails horribly when you look at things like trig functions (what’s the error distribution on the tangent of an angle that’s close to 90º?). Or even just division, dividing by something that’s close to zero (which is the cause of the tangent issue). To do it really properly, you’d need a full specification of every error distribution, and I don’t think there’s any good way to do that.

Sorry. I originally had it written the other way, then scrolled up to see I’d written the wrong function. I fixed the code, but forgot about the comment.

I guess that is one down side to my commenting habit.

The only one I know of is Hz^0.5, and that one is fairly easy to avoid. Maybe you know of others.

It’s only a little less complicated to implement rational powers in the type system. I’m not sure about the one leahcim linked to. Apparently F# started with integer powers but added rationals eventually.

Please don’t tell me that someone has a use case for irrational powers :slight_smile: .

At the very lowest levels, you need a way of stripping the types to implement these things. But allowing “add” on temperature is still a bad idea. Instead, present a weighted sum operation.

Personally, if I were implementing something for my own use, the core system would operate only in SI. Conversion to equivalent types would be a layer on top of that (and only used for presentation to the user).

I was replying to the OP’s exact question. Whereas everything about functions you wrote is true, I don’t believe it applies to the OP’s use case. My comment stands.

My guess would be that the calculator is storing everything internally in SI, but storing information along with it specifying what units the user wanted.

But then again, knowing how HP’s engineers worked, more likely the internals are based on some completely counterintuitive and baffling procedure that their research showed saved three clock cycles and 6.5 bits of storage in 20% of use cases. They have rather a habit of re-inventing the wheel, and ending up with some very nice, but highly overpriced, wheels in the process.

RPN is so beautiful that I can forgive all other sins.

I’d say calculators are a very different beast than a general programming language. You want to see the intermediate results in a familiar form, and conversions are common. Most programming doesn’t have that requirement.

I find that in actual practice it’s very common for the variable passed in to the function to have the same name as the variable the parameter becomes inside the function. This is because if you have a function that returns the number of accidents happening on a given freeway (for example), then good self-documenting code will make that parameter be called “freewayID” or somesuch thing, and the code that calls it, being good self-documenting code, will also call the variable “freewayID”, because that’s what the thing is. I rarely find it useful to decorate the name of the calling variable with anything more specific, unless you need to do so to keep track of which of several freewayIDs you’re dealing with (which certainly happens).

Sure, if your function’s parameter is something like temperature, it often makes sense to have the name describe what it’s the temperature of, but when you’re passing the freewayID from one function to another to another to another as you do various different things with the freeway in question, it often just makes sense to call it the same thing (ie: what it is) at every step of the process. The rule of thumb here is your code should be self-documenting and make sense, not that you should bias either towards or away from recycling names.

Does the calling code only deal with one freeway at a time? More likely, any program dealing with any freeway at all would have many different freeways, each of which would need its own name describing why it’s relevant in the program.

Though of course it will sometimes happen that you’re using the same variable name in both places.

It’s really common to have multiple functions be called on the same ID, whether it be a freeway or something else.

Consider something like this: We want to figure out a hypothetical toll on a freeway, which involves getting the current price of the freeway based on congestion. We might do something like this:

float getFreewayPrice(int CarID)
{
   int freewayID=getCurrentFreeway(CarID);

   float freewayCost=getFreewayCost(freewayID):

  return freewayCost;
}

float getFreewayCost(int FreewayID)
{
  double carCount=getCarCount(FreewayID);
  
  float freewayCost=getCongestionPrice(FreewayID, carCount);

  return freewayCost;
}

float getCongestionPrice(int FreewayID, double CarCount)
{
   double carCapacity=getCarCapacity(FreewayID);
   float percentageOfCapacity=CarCount / carCapacity;

   float congestionPrice=getPriceByPercentqgeOfCapacity(percentageOfCapacity);

   return congestionPrice;
}

So we had to pass the same ID repeatedly through multiple functions. The convention I used is that if the variable starts with lowercase, it was defined in the current function. If it has an uppercase first letter, it’s passed in as a parameter. If it had been a global, it could have been _freewayID.

I’m not saying this is the right convention. The proper convention is whatever your company’s code practices set out, and it’ll be different for different languages, most likely. But some convention will be used to sort it all.

Another good example is a web session cookie, which essentially gives you an ID for all your context. It gets passed in the header on every transaction, and the web server will pass it all over the place while running the code to serve up your page.

I realize it’s just an example, but it’s bad design for freeway and car IDs to have the same type. It should be a compile error to pass the wrong kind of to a function. Even in straight C, you would preferentially have different structs for freeways and cars, even if internally they were just an int ID. That would also reduce dumb errors like adding two IDs together.