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

问题描述 投票:0回答:6

我不知道这是否被认为是一个好的编程实践,但就我个人而言,我发现通过命名函数的参数来调用函数可以使代码更具可读性。我不知道这在 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)
rust
6个回答
24
投票

因此我的问题是:在 Rust 中可以在函数调用中命名参数吗

Rust 不支持命名参数作为语言的一部分。

根据 Rust 最佳实践,这是否被认为是一个好的实践? (我是初学者)

通常不会(相当强的类型通常有助于缓解这个问题)

在确实有用的情况下,两种模式会反复出现:

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

请参阅链接到 https://old.reddit.com/r/rust/comments/fg6vrn/for_your_consideration_an_alternative_to_the/ 的文章以获取更多信息(我链接到该线程,因为对选项也有有用的讨论)作为有用的板条箱的链接)。


22
投票

关于此主题的 RFC 开放

虽然这个 RFC 中并不是每个人都同意,但似乎普遍支持向 Rust 添加命名和默认参数(包括核心团队的支持)。看来主要的障碍不是在概念上,而是在实施上。

如 RFC 中所述,替代方案(例如构建器模式)与内置命名参数和默认参数具有相同的问题,而且还添加了大量样板文件。


8
投票

不,Rust 中没有命名/关键字参数。它们已经讨论了很长时间,但还没有添加它们的具体计划。

如果函数中有很多参数,请考虑传递结构体、构建器模式等。

顺便说一句:

add()
示例没有显示为什么命名/关键字参数可能有用,因为这些参数是可以互换的。


3
投票

如果您每晚都在,您可以使用

#![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)
    )
}

优点:

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

坏处

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

1
投票

该语言中没有命名参数,但可以用宏来模拟它们。请参阅 https://crates.io/crates/named 了解实验性解决方案。


0
投票

如何使用

struct
实现此目的的具体示例,对于 Rust 新手(比如我自己),请考虑您具有此功能:

fn my_function(age: usize, money: f64, name: String) {
    println!("Hi {name}! You are {age} years old and have {money} $");
}

你能做的是:

struct MyFunctionArgs {
    age: usize, money: f64, name: String,
}
fn my_function(args: MyFunctionArgs) {
    let age = args.age;
    let money = args.money;
    let name = args.name;
    println!("Hi {name}! You are {age} years old and have {money} $");
}

fn main() {
    my_function(MyFunctionArgs {
        name: String::from("Juan Carlos"),
        age: 25,
        money: 40.,
    });
}

除了添加的样板之外,我不确定这样做的后果。但似乎有效。

© www.soinside.com 2019 - 2024. All rights reserved.