匿名结构体类型作为函数参数

5

在Typescript中,我可以这样做:

function foo(param: { a: string, b: number }) { }

为了声明一个接收对象的函数,而不显式地将参数类型声明为命名类型,可以这样写:

interface Parameter {
    a: string;
    b: number;
}

function foo(param: Parameter) {}

有没有一种方法可以在 Rust 中实现这个,或者我必须显式地将参数类型声明为命名类型?
3个回答

4
Rust 对元组、数组和结构体的函数参数有模式解构功能,用法如下:
fn f((a, b): (u32, i32), [x, y, z]: [String; 3]) { }
struct A { a: u32, b: String }
fn g(A { a, b }: A) { }

但是在Rust中没有未命名类型/对象的语法,因为对象在Rust中根本不存在。

想象一下如果Rust有这样的语法:

fn f(param: {a: String, b: String}) {} // Invalid code!

有人如何调用那个函数呢?没有办法构造此类型的实例对象。在 JavaScript / TypeScript 中这是可能的,因为有动态类型,但是在 Rust 中,您必须知道一个类型才能够构造它。
如果您对在函数中模拟关键字参数感兴趣,这个链接可能会有所帮助:如何在 Rust 中最好地*伪造*关键字样式的函数参数? 如果您想要给元组命名以及为其参数命名,则可以使用不稳定的bindings_after_at功能来启用此语法:
#![feature(bindings_after_at)]
fn f(my_tuple @ (a, b): (u32, u32)) {
    println!("this: {:?}", my_tuple);
    println!("is the same as: {:?}", (a, b));
}
// or this
fn g(arr @ [.., tail] : [u32; 5]) {
    println!("this: {}", arr[4]);
    println!("is the same as: {}", tail);
}

3

您可以使用元组:

fn foo(param: (String, usize)) {
    let a: String = param.0;
    let b: usize = param.1;
}

与结构体不同,元组的值是通过索引来访问的。对元组进行解构可以更轻松地跟踪其值。
fn foo((a, b): (String, usize)) {
    // you can now access `a` and `b` here
}

2
由于Rust采用了名义类型系统,您无法执行此类操作,而您的代码是结构类型系统的示例。您可以在维基百科上阅读有关它们的信息: https://en.wikipedia.org/wiki/Nominal_type_system https://en.wikipedia.org/wiki/Structural_type_system 在结构类型系统中,类型只是其字段的集合,其名称和定义并不重要。相比之下,名义类型系统将具有不同声明但具有相同字段集的两种类型视为不同(这意味着类型的名称比内容更重要)。
Rust选择了名义类型系统,因为它更加严格,并允许在类型级别上强制执行某些程序属性。考虑以下示例:
struct Employee(String);
struct Customer(String);

fn handle_order(employee: Employee, customer: Customer){}

如果程序员犯了一个错误,并像这样调用它 handle_order(customer, employee),在具有结构类型的语言中不会被注意到,但在名义类型中会触发编译错误。
此外,还可能出现这样的情况,即程序员需要更改类型的定义,例如向 Employee 添加字段。在这种情况下,可以确保在修复 Employee 的所有用途后完成重构。在具有结构类型的程序中,无法确定是否完成了重构,因为可能存在发送 Customer 而不是 Employee 的代码,因此结构类型程序的重构要困难一些。
Rust 中名义类型的另一个著名例子是生命周期。具有相同定义类型和不同生命周期的类型变量实际上具有不同的名义类型。而 Rust 的所有安全性都基于此。
Typescript 使用结构类型,因为将其映射到 JavaScript 更容易。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接