在Rust中是否可以通过命名参数来调用函数?

l7wslrjt  于 2023-05-18  发布在  其他
关注(0)|答案(5)|浏览(187)

我不知道这是否被认为是一个好的编程实践,但就我个人而言,我发现通过命名参数来调用函数会使代码更具可读性。我不知道这在Rust编程语言中是否可能。我在语法中没有找到任何命名的调用表达式:
https://doc.rust-lang.org/reference/expressions/call-expr.html
例如,下面的代码无法编译:

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

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

因此,我的问题是:在Rust中,函数调用中的参数命名是否可行?如果答案是肯定的,根据Rust的最佳实践,这是否被认为是一种良好的实践?(我是初学者)
环境:

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

e5njpo681#

因此,我的问题是:Rust中函数调用中的参数命名是否可行
Rust不支持命名参数作为语言的一部分。
根据Rust的最佳实践,它是否被认为是一个良好的实践?(我是初学者)
一般不会(较强的类型通常有助于缓解此问题)
在它确实有用的情况下,两种模式会反复出现:

  • 一个 options struct,该函数将具有有限数量的简单参数和一个命名结构,以传递更多的结构化数据,提供“命名”
  • builder模式,它是前者的一个进化的、更有文化的版本(并且更有利于 * 可选 * 参数)

请参阅链接到https://old.reddit.com/r/rust/comments/fg6vrn/for_your_consideration_an_alternative_to_the/的文章以获取更多信息(我链接到该线程是因为其中有关于选项的有用讨论,以及指向有用crates的链接)。

u7up0aaq

u7up0aaq2#

an RFC open on this topic
虽然不是每个人都同意这个RFC,但似乎普遍支持向Rust添加命名和默认参数(包括核心团队的支持)。看来主要的障碍不在于概念,而在于执行。
正如RFC中所指出的,替代方案(如构建器模式)与内置的命名和默认参数具有相同的问题,但也增加了大量的样板。

zbq4xfa0

zbq4xfa03#

Rust中没有named/keyword参数。它们已经被讨论过for a long time,但没有具体的计划来添加它们。
如果你在一个函数中有很多参数,考虑传递一个结构体,构建器模式等。
顺便说一下:add()示例并没有说明为什么named/keyword参数是有用的,因为参数是可互换的。

rfbsl7qr

rfbsl7qr4#

如果你每晚都在,你可以用#![feature(adt_const_params)]来解决这个问题。它允许您使用&'static str常量作为类型参数。它很笨重,但它仍然是迄今为止我能想到的最好的:

#![feature(adt_const_params)]

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

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

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

优点:

  • 如果参数的名称有误,或者试图以不正确的顺序使用它们,编译器将出错;
  • 无宏;
  • 每个函数中的每个参数都没有新类型;
  • 与构建器模式不同,您不能多次设置相同的参数。

《The Bad》

  • 没有什么能保证函数参数的实际名称和您使用的const &'static str是相同的,这令人失望,但不太容易出错;
  • 可以有多个同名参数;
  • 调用站点上的语法相当冗长;
  • 从参数中获取值需要像示例中那样进行解构(感谢@Chayim Friedman)或类似person_name.0的东西;
  • 你不能改变参数的顺序,尽管这很小。
r7s23pms

r7s23pms5#

语言中没有命名参数,但可以用宏模拟它们。参见https://crates.io/crates/named以获得实验解决方案。

相关问题