Hacker News new | ask | show | jobs
by flohofwoe 1740 days ago
As pointed out in some of the article's comments, a much better solution would be if all languages allowed putting the name in front of function parameters (and while at it, also not enforce a specific parameter order and skip default-value parameters).

A workaround in C99 (and more limited in C++20) is to use a single struct which bundles all the function parameters, and then use designated initialization, this also makes function paramaters optional, and at least in C99 they can appear in any order:

    my_func((my_struct_t){
        .a_bool_flag = true,
        .another_bool_flag = false,
        .a_string = "Hello World"
    });
This is mainly useful for functions which take many parameters. One downside in C99 (but not C++) is that there's no way to define default values for struct items (other than zero/false).
6 comments

In Julia you have positional and keyword arguments, separated by a semicolon.

  function f(; a, b)
    a+b
  end
Default values are optional. This can only be called with named arguments like f(; a=5, b=7). Unfortunately the separation isn't required to be explicit when calling the function, so calling f(a=5, b=7) also works. Generally calling functions is extremely permissive (e.g. a function with two positional and two keyword arguments function g(a, b=5; c, d=8) can be called with keywords and positions interleaved g(1, c = 7, 5)), leading to potential confusion at the call site. Our coding guidelines enforce separation of positional and keyword at call sites, and with that additional restriction I have found Julias behaviour in this regard very pleasant. E.g.:

  calc_something(a, b; bool_flag=true)
is the best style for this type of thing that I have seen.
Many newer languages support named function arguments: Swift, Kotlin, etc.
Some rather old fashioned languages do as well... for example PostgreSQL's PL/pgSQL supports named function arguments, too.
For C* langs you can just insert a block comment with the arg name:

  my_func(/*a_bool_flag*/ true, yadda);
The downside to this approach is it often doesn't survive refactors. People change the method signature, update call sites, and often ignore the comments. Named parameters avoid this downside, it's a real shame named parameters are not more common in languages.
Linters can check for this sort of thing, for example Error Prone[0] has a lint[1] for this.

Totally agree this is better to be in the language proper so we don't need this extra tooling.

[0]: https://errorprone.info

[1]: https://errorprone.info/bugpattern/ParameterName

This even works in latest MSVC as well as clang and gcc!

https://pdimov.github.io/blog/2020/09/07/named-parameters-in...

Yep, in C mode (not C++) this has been working in MSVC already since VS2015. Clang also allowed the full C99 designated intitialization feature set in C++ long before C++20 as non-standard language extension.
In JS we can use JSON/object literal syntax and object destructuring to serve a similar purpose:

    myFunc({
        aBoolFlag : true,
        anotherBoolFlag : false,
        aString : "Hello World"
    });

    const myFunc = ({ aBoolFlag, anotherBoolFlag, aString }) => { /* do something with them... */ };
I started doing this because of React but at this point ({}) is my default way of starting a function. The only thing I dislike is that it's not super ergonomic for explicit typescript declarations (but great when using typescript to check .js files).
I don't find it too bad to do

  interface IFunctionParameters {
    userId: string;
    name: string;
    age: number;
  }

  const example = ({userId, name, age}: IFunctionParameters) => {...}
The most annoying thing about this to me (and to be clear, I do exactly this all the time) is when you mouseover `example` at a use site, all you see is `IFunctionParameters`, not the definition of `IFunctionParameters`. At least in VS Code.
That's a good point, I've lost count of the times I've hovered my mouse over that IFunctionParameters tooltip expecting a nested tooltip to appear with the actual types
Kotlin does this, and I find it’s massively improved the readability of our codebase