tipo de estrutura anônima para parâmetro de função

Dec 23 2020

No texto datilografado, posso fazer o seguinte:

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

Para declarar uma função que aceita um objeto, sem declarar explicitamente o tipo de parâmetro como um tipo nomeado como este:

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

function foo(param: Parameter) {}

Existe uma maneira de fazer isso no Rust, ou tenho que declarar explicitamente o tipo de parâmetro como um tipo nomeado?

Respostas

3 Natrix Dec 24 2020 at 05:03

Rust tem desconstrução de padrão para parâmetros de função em tuplas, matrizes e estruturas como este:

fn f((a, b): (u32, i32), [x, y, z]: [String; 3]) { }
struct A { a: u32, b: String }
fn g(A { a, b }: A) { }

Mas não tem essa sintaxe para tipos / objetos sem nome, uma vez que os objetos simplesmente não existem na ferrugem. Imagine que a ferrugem tem uma sintaxe para isso:

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

Como alguém chamaria essa função? Não há como construir uma instância desse tipo. Em javascript (/ typescript) isso é possível, por causa da tipagem dinâmica, mas na ferrugem você precisa saber um tipo para poder construí-lo.

Se você estiver interessado em falsificar argumentos de palavra-chave em funções, isso pode ajudar: Como melhor * falsificar * argumentos de função de estilo de palavra-chave no Rust?

Se você quiser dar um nome às tuplas, além de ter um nome para seus parâmetros, existe o bindings_after_atrecurso instável que permite esta sintaxe:

#![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);
}
2 IbraheemAhmed Dec 24 2020 at 03:51

Você pode usar uma tupla:

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

Em vez de ter campos nomeados como structs, os valores de tupla são indexados. A desestruturação da tupla torna um pouco mais fácil acompanhar os valores:

fn foo((a, b): (String, usize)) {
    // you can now access `a` and `b` here
}
2 AngelicosPhosphoros Dec 24 2020 at 19:11

Você não pode fazer essas coisas no Rust porque ele tem um sistema de tipo nominal e seu código é um exemplo de sistemas de tipo estrutural. Você pode ler sobre eles na wikipedia:https://en.wikipedia.org/wiki/Nominal_type_system https://en.wikipedia.org/wiki/Structural_type_system

No sistema de tipo estrutural, o tipo é apenas um conjunto de seus campos e seu nome e definição não importa. Em contraste, o sistema de tipo nominal trata 2 tipos com declarações diferentes, mas o mesmo conjunto de campos como diferentes (o que significa que o nome do tipo é mais importante do que o conteúdo).

Rust escolhido nominal porque é mais resistente e permite impor algumas propriedades do programa no nível de tipo. Considere este exemplo:

struct Employee(String);
struct Customer(String);

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

Se o programador cometeu um erro e chamou assim handle_order(customer, employee), é um erro que não seria notado em linguagem com tipagem estrutural, mas desencadearia um erro de compilação na tipagem nominal.

Além disso, pode haver situações em que o programador precise alterar a definição do tipo, por exemplo, adicionar um campo ao Employee. Nesse caso, pode-se ter certeza de que a refatoração será feita quando todos os usos de Employee forem corrigidos. Em um programa com tipagem estrutural, não se pode ter certeza porque pode haver um código que envia Cliente em vez de e, portanto, a refatoração de programas com tipagem estrutural é um pouco mais difícil.

Outro exemplo famoso de digitação nominal em Rust são os tempos de vida . Variáveis ​​com tipos com o mesmo tipo definido e diferentes vidas úteis, na verdade, têm diferentes tipos nominais. E toda a segurança do Rusts é baseada nisso.

O Typescript usa tipagem estrutural porque é mais fácil mapeá-lo em JavaScript.