işlev parametresi için anonim yapı türü

Dec 23 2020

Typescript'te bunu yapabilirim:

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

Parametre türünü açıkça şu şekilde adlandırılmış bir tür olarak bildirmeden, bir nesneyi alan bir işlevi bildirmek için:

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

function foo(param: Parameter) {}

Bunu Rust'ta yapmanın bir yolu var mı, yoksa parametre türünü açıkça adlandırılmış bir tür olarak belirtmem gerekiyor mu?

Yanıtlar

3 Natrix Dec 24 2020 at 05:03

Rust, tuplelar, diziler ve yapılardaki fonksiyon parametreleri için şuna benzer desen yapısökümüne sahiptir:

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

Ancak, adsız türler / nesneler için böyle bir sözdizimi yoktur, çünkü nesneler basitçe pas halinde yoktur. Rust'ın bunun için bir sözdizimi olduğunu hayal edin:

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

Birisi bu işlevi nasıl çağırır? Bu türden bir örnek oluşturmanın bir yolu yoktur. Javascript'te (/ typescript) bu, dinamik yazım nedeniyle mümkündür, ancak pas durumunda, onu oluşturabilmek için bir türü bilmeniz gerekir.

Fonksiyonlarda anahtar kelime argümanları taklit etmekle ilgileniyorsanız, bu size yardımcı olabilir: Rust'ta anahtar kelime stili fonksiyon argümanları en iyi * sahte * nasıl yapılır?

Demetlere bir isim vermek ve parametrelerine bir isim vermek isterseniz, bindings_after_atbu sözdizimini etkinleştiren kararsız- özelliği vardır :

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

Bir demet kullanabilirsiniz:

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

Yapılar gibi adlandırılmış alanlara sahip olmak yerine, tuple değerleri dizine alınır. Demoyu yok etmek, değerleri takip etmeyi biraz daha kolaylaştırır:

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

Rust'ta böyle şeyler yapamazsınız çünkü nominal tip sistemi vardır ve kodunuz yapısal tip sistemlere örnektir. Onlar hakkında Wikipedia'da okuyabilirsiniz:https://en.wikipedia.org/wiki/Nominal_type_system https://en.wikipedia.org/wiki/Structural_type_system

Yapısal tip sisteminde, tip sadece alanlarından oluşur ve adı ve tanımı önemli değildir. Buna karşılık, nominal tip sistemi, farklı bildirime sahip 2 türü, ancak aynı alan kümesini farklı olarak ele alır (yani, türün adı içerikten daha önemlidir).

Rust, daha zorlayıcı olduğu ve programın bazı özelliklerinin tür düzeyinde uygulanmasına izin verdiği için nominal olarak seçilmiştir. Şu örneği düşünün:

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

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

Programcı bir hata yaparsa ve ona böyle seslenirse handle_order(customer, employee), bu yapısal yazımla dilde fark edilmeyecek, ancak nominal yazmada derleme hatasını tetikleyebilecek bir hatadır.

Ayrıca, programcının tür tanımını değiştirmesi gerektiğinde, örneğin Employee. Böyle bir durumda, Çalışanın tüm kullanımları düzeltildiğinde yeniden düzenleme yapılacağından emin olunabilir. Yapısal tipleme ile programda, kimse emin olamaz çünkü Müşteri yerine gönderen bir kod olabilir ve bu nedenle yapısal tipte programların yeniden düzenlenmesi biraz daha zordur.

Rust'ta nominal yazmanın bir başka ünlü örneği yaşam süreleridir . Aynı tanımlanmış tip ve farklı ömürlere sahip tiplere sahip değişkenlerin aslında farklı nominal tipleri vardır. Ve tüm Rusts güvenliği buna dayanmaktadır.

TypeScript, yapısal yazımı kullanır çünkü onu JavaScript ile eşlemek daha kolaydır.