Có cách nào nhanh hơn / ngắn hơn để khởi tạo các biến trong cấu trúc Rust không?


102

Trong ví dụ sau, tôi muốn gán một giá trị cho mỗi trường trong cấu trúc trong khai báo các trường. Ngoài ra, cần một câu lệnh bổ sung cho mỗi trường để gán giá trị cho các trường. Tất cả những gì tôi muốn có thể làm là gán các giá trị mặc định khi cấu trúc được khởi tạo.

Có cách nào ngắn gọn hơn để làm điều này không?

struct cParams {
    iInsertMax: i64,
    iUpdateMax: i64,
    iDeleteMax: i64,
    iInstanceMax: i64,
    tFirstInstance: bool,
    tCreateTables: bool,
    tContinue: bool,
}

impl cParams {
    fn new() -> cParams {
        cParams {
            iInsertMax: -1,
            iUpdateMax: -1,
            iDeleteMax: -1,
            iInstanceMax: -1,
            tFirstInstance: false,
            tCreateTables: false,
            tContinue: false,
        }
    }
}

Câu trả lời:


161

Bạn có thể cung cấp các giá trị mặc định cho cấu trúc của mình bằng cách triển khai Defaultđặc điểm. Các defaultchức năng sẽ trông như thế hiện tại của bạn newchức năng:

impl Default for cParams {
    fn default() -> cParams {
        cParams {
            iInsertMax: -1,
            iUpdateMax: -1,
            iDeleteMax: -1,
            iInstanceMax: -1,
            tFirstInstance: false,
            tCreateTables: false,
            tContinue: false,
        }
    }
}

Sau đó, bạn có thể khởi tạo cấu trúc bằng cách chỉ cung cấp các giá trị không mặc định:

let p = cParams { iInsertMax: 10, ..Default::default() };

Với một số thay đổi nhỏ đối với cấu trúc dữ liệu của bạn, bạn có thể tận dụng lợi thế của việc triển khai mặc định được dẫn xuất tự động. Nếu bạn sử dụng #[derive(Default)]trên một cấu trúc dữ liệu, trình biên dịch sẽ tự động tạo một hàm mặc định cho bạn để điền vào mỗi trường với giá trị mặc định của nó. Giá trị boolean mặc định là false, giá trị tích phân mặc định là 0.

Giá trị mặc định của một số nguyên là 0 là một vấn đề ở đây vì bạn muốn các trường số nguyên là -1 theo mặc định. Bạn có thể xác định một kiểu mới thực hiện giá trị mặc định là -1 và sử dụng giá trị đó thay vì i64trong cấu trúc của bạn. (Tôi chưa thử nghiệm điều đó, nhưng nó sẽ hoạt động).

Tuy nhiên, tôi khuyên bạn nên thay đổi một chút cấu trúc dữ liệu của bạn và sử dụng Option<i64>thay vì i64. Tôi không biết ngữ cảnh mã của bạn, nhưng có vẻ như bạn đang sử dụng giá trị đặc biệt của -1 để biểu thị ý nghĩa đặc biệt "vô hạn" hoặc "không có giá trị tối đa". Trong Rust, chúng tôi sử dụng một Optionđể đại diện cho một giá trị hiện tại tùy chọn. Không cần phải hack -1. Một tùy chọn có thể là một trong hai Nonehoặc Some(x)trong đó x sẽ là của bạn i64ở đây. Nó thậm chí có thể là một số nguyên không dấu nếu -1 là giá trị âm duy nhất. OptionGiá trị mặc định là None, vì vậy với các thay đổi được đề xuất, mã của bạn có thể trông giống như sau:

#[derive(Default)]
struct cParams {
    iInsertMax: Option<u64>,
    iUpdateMax: Option<u64>,
    iDeleteMax: Option<u64>,
    iInstanceMax: Option<u64>,
    tFirstInstance: bool,
    tCreateTables: bool,
    tContinue: bool,
}

let p = cParams { iInsertMax: Some(10), ..Default::default() };

1
Cảm ơn, tôi đã đọc nhanh, nhưng tôi sẽ đọc lại để hiểu rõ hơn. Các mặc định "tự nhiên" mà một số ngôn ngữ sử dụng, chẳng hạn như tôi tin là không, sai, "", v.v., sẽ phù hợp với tôi. Tôi hiểu rằng có nhiều hàm ý hơn là "vấn đề" nhỏ của tôi cần giải quyết. Khả năng nêu vd. "iVal: i64 = 0", sẽ giải quyết nhu cầu rộng lớn hơn của tôi, nhưng tôi đoán điều đó sẽ không xảy ra. "# [Dẫn xuất (Mặc định)]" sẽ giải quyết hầu hết các mong muốn của tôi. Tôi không chắc tại sao tôi lại sử dụng -1 trong chương trình thử nghiệm của mình, nhưng nó không cần thiết (lịch sử). Sẽ rất hữu ích (IMHO) để có thể chỉ định một giá trị tại chỗ mà trường được xác định.
Brian Oh

9
@BrianOh, theo cách tiếp tuyến, "giá trị mặc định cho trường cấu trúc" (tức là một cái gì đó tương tự struct Foo { val: i64 = 0 }) đã được đề xuất và vì vậy có thể xuất hiện trong các phiên bản sau.
huon

Sẽ rất tốt nếu điều đó được triển khai IMO - "struct foo {....". Tôi đã thực hiện các thay đổi theo đề xuất của bạn, sử dụng cấu trúc như được viết trong câu hỏi của tôi và với cấu trúc mặc định. Điều đó chắc chắn phù hợp với tôi hơn và ngắn gọn hơn nhiều. Không quen với cú pháp, một vấn đề nhỏ mà tôi gặp phải là không biết cú pháp cho TẤT CẢ các mặc định. IE: Tôi đã sử dụng "= cParams {iInsertMax: 10, ..Default :: default ()};", nhưng tôi thực sự muốn "iInstanceMax" cũng là một mặc định. IMO nên cho "# [dẫn xuất (Mặc định)]" trở thành một phần của cấu trúc, nhưng tôi đoán lựa chọn thay thế phù hợp với trình biên dịch hơn.
Brian Oh,

2
Rất cám ơn vì điều đó. IMHO các giá trị mặc định phải là mặc định. I E. Tôi không nghĩ rằng cần phải chỉ định Mặc định: mặc định, v.v. Tôi cũng nghĩ rằng các trường có thể được gán một giá trị khi chúng được xác định. Đó chỉ là quan điểm đơn giản của tôi, và tôi nhận ra rằng Rust được thiết kế để an toàn và có một góc nhìn rộng hơn nhiều so với tôi. Khi một người đang học ngôn ngữ (hoặc ít nhất là tôi), việc triển khai hiện tại có vẻ hơi rườm rà. Rust không phải là một ngôn ngữ đơn giản IMHO, và càng có thể thực hiện được nhiều điều khả thi để đơn giản hóa nó thì ít nhất là tốt hơn cho tôi.
Brian Oh

2
Có cần phải xác định giá trị mặc định cho tất cả các trường khi triển khai Defaultcho một cấu trúc không?
Matthew Stevenson
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.