Is it possible to call a function in Rust by naming its arguments?

Viewed 5198

I don't know whether this is considered to be a good programming practice but personally, I find that calling a function by naming its arguments makes the code more readable. I don't know whether this is possible in Rust programming language. I didn't find any named call expression in the grammar:

https://doc.rust-lang.org/reference/expressions/call-expr.html

So for example the following doesn't compile:

fn add(n1 : i32, n2 : i32) -> i32 {
    n1 + n2
}


fn main() {
    let sum_value = add(n1 = 124, n2 = 200);
    println!("sum = {}", sum_value);
}

Therefore my question is: Is naming arguments in function call is possible in Rust and if the answer is yes, is it considered to be a good practice according to Rust best practices? (I'm a beginner)

Environment:

OS: Linux Ubuntu MATE 20.04.1 (64 bits)
rustc --version: rustc 1.46.0 (04488afe3 2020-08-24)
5 Answers

Therefore my question is: Is naming arguments in function call is possible in Rust

Rust does not support named parameters as part of the language.

is it considered to be a good practice according to Rust best practices? (I'm a beginner)

Generally not (the rather strong typing usually helps mitigate this issue)

In cases where it really is useful two patterns crop up repeatedly:

  • an options struct, the function would have a limited number of simple parameters and a named structure to pass more structured data, providing "naming"
  • the builder pattern, which is an evolved and more literate version of the former (and more conducive to optional parameters)

See the article linked to https://old.reddit.com/r/rust/comments/fg6vrn/for_your_consideration_an_alternative_to_the/ for more information (I'm linking to the thread because there is useful discussion of the options, as well as links to helpful crates).

There is an RFC open on this topic.

Although not everyone in this RFC agrees, it seems that there is generally support for adding named and default parameters to Rust (including support from the core team). It seems the primary obstacle is not in the concept, but in the implementation.

As noted in the RFC, alternatives (such as the builder pattern) have the same issues as built-in named and default parameters, but also add large amounts of boilerplate.

No, there are no named/keyword parameters in Rust. They have been discussed for a long time, but there are no concrete plans to add them.

If you have many parameters in a function, consider passing a struct, the builder pattern, etc.

By the way: the add() example does not show why named/keyword parameters could be useful, since the parameters are interchangeable.

You can work around it with #![feature(adt_const_params)] if you're in nightly. It allows you to use &'static str contants as type parameters. It's clunky but it's still the best I could come up with so far:

#![feature(adt_const_params)]

pub struct Param<const NAME: &'static str, T>(pub T);

fn foo(
    person_name: Param::<"person_name", String>,
    age: Param::<"age", u8>,
){
    println!("{} is {} years old", person_name.0, age.0)
}

fn main() {
    foo(
        Param::<"person_name", _>("Bob".to_owned()),
        Param::<"age", _>(123)
    )
}

The Good:

  • The compiler will error out if you get the names of the params wrong, or if you try to use them in the incorrect order;
  • No macros;
  • No new types for every parameter in every function;
  • Unlike the builder pattern, you can't set the same parameter multiple times.

The Bad

  • Nothing guarantees that the actual name of the parameter and the const &'static str that you used are identical, which is disappointing but not very error prone;
  • Syntax is pretty verbose on the call site;
  • Getting the value out of the parameter always needs something like some_parameter.0, which gets annoying.

There are no named parameters in the language, but they can be emulated with macros. See https://crates.io/crates/named for an experimental solution.

Related