Di TypeScript, saya bisa melakukan ini:

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

Untuk mendeklarasikan fungsi yang mengambil objek, tanpa secara eksplisit mendeklarasikan tipe parameter sebagai tipe bernama seperti ini:

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

function foo(param: Parameter) {}

Apakah ada cara saya bisa melakukan ini di Rust, atau apakah saya harus secara eksplisit mendeklarasikan tipe parameter sebagai tipe bernama?

3
Roymunson 24 Desember 2020, 06:24

3 jawaban

Jawaban Terbaik

Rust memiliki dekonstruksi pola untuk parameter fungsi pada tupel, array, dan struct seperti ini:

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

Tetapi tidak memiliki sintaks seperti itu untuk tipe/objek yang tidak disebutkan namanya, karena objek tidak ada di rust. Bayangkan rust memiliki sintaks untuk ini:

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

Bagaimana seseorang memanggil fungsi itu? Tidak ada cara untuk membangun sebuah instance dari jenis ini. Dalam javascript (/ Typescript) ini dimungkinkan, karena pengetikan dinamis, tetapi dalam karat Anda harus mengetahui tipe untuk dapat membangunnya.

Jika Anda tertarik untuk memalsukan argumen kata kunci dalam fungsi, ini mungkin membantu: Bagaimana cara terbaik argumen fungsi gaya kata kunci *palsu* di Rust?

Jika Anda ingin memberi nama tupel serta menamai parameternya, ada fitur bindings_after_at yang tidak stabil yang mengaktifkan sintaks ini:

#![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
Natrix 24 Desember 2020, 05:03

Anda dapat menggunakan tupel:

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

Daripada memiliki bidang bernama seperti struct, nilai Tuple diindeks. Menghancurkan Tuple membuatnya sedikit lebih mudah untuk melacak nilai-nilai:

fn foo((a, b): (String, usize)) {
    // you can now access `a` and `b` here
}
2
Ibraheem Ahmed 24 Desember 2020, 03:51

Anda tidak dapat melakukan hal seperti itu di Rust karena memiliki sistem tipe nominal dan kode Anda adalah contoh sistem tipe struktural. Anda dapat membaca tentang mereka di wikipedia: https://en.wikipedia.org/wiki/Nominal_type_system https://en.wikipedia.org/wiki/Structural_type_system

Dalam sistem tipe struktural, tipe hanya mengatur bidangnya dan nama serta definisinya tidak masalah. Sebaliknya, sistem tipe nominal memperlakukan 2 tipe dengan deklarasi berbeda tetapi kumpulan bidang yang sama berbeda (artinya, nama tipe lebih penting daripada konten).

Karat dipilih nominal karena lebih ketat dan memungkinkan untuk menegakkan beberapa properti program pada tingkat tipe. Pertimbangkan contoh ini:

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

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

Jika programmer membuat kesalahan dan menyebutnya seperti handle_order(customer, employee), itu adalah kesalahan yang tidak akan diperhatikan dalam bahasa dengan pengetikan struktural tetapi akan memicu kesalahan kompilasi dalam pengetikan nominal.

Juga, mungkin ada situasi ketika programmer perlu mengubah definisi tipe, misalnya, menambahkan bidang ke Employee. Dalam kasus seperti itu, dapat dipastikan bahwa refactoring dilakukan ketika semua penggunaan Employee diperbaiki. Dalam program dengan pengetikan struktural, seseorang tidak dapat memastikan karena mungkin ada kode yang mengirim Pelanggan alih-alih dan dengan demikian refactoring program yang diketik struktural sedikit lebih sulit.

Contoh lain yang terkenal dari pengetikan nominal di Rust adalah lifetimes. Variabel dengan tipe dengan tipe terdefinisi yang sama dan lifetime yang berbeda sebenarnya memiliki tipe nominal yang berbeda. Dan semua keamanan Rusts didasarkan pada ini.

TypeScript menggunakan pengetikan struktural karena lebih mudah untuk memetakannya ke dalam JavaScript.

2
Angelicos Phosphoros 24 Desember 2020, 19:11