Apakah ada cara yang lebih cepat / lebih singkat untuk menginisialisasi variabel di struct Rust?

102

Dalam contoh berikut, saya lebih suka memberikan nilai ke setiap bidang di struct di deklarasi bidang. Atau, secara efektif dibutuhkan satu pernyataan tambahan untuk setiap bidang untuk menetapkan nilai ke bidang. Yang ingin saya lakukan adalah menetapkan nilai default saat struct dibuat.

Apakah ada cara yang lebih ringkas untuk melakukan ini?

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,
        }
    }
}
Brian Oh
sumber

Jawaban:

162

Anda dapat memberikan nilai default untuk struct Anda dengan menerapkan Defaultsifat tersebut. The defaultfungsi akan terlihat seperti Anda saat ini newfungsi:

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

Anda kemudian dapat membuat instance struct dengan hanya memberikan nilai non-default:

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

Dengan beberapa perubahan kecil pada struktur data Anda, Anda dapat memanfaatkan implementasi default yang diturunkan secara otomatis. Jika Anda menggunakan #[derive(Default)]pada struktur data, kompilator akan secara otomatis membuat fungsi default untuk Anda yang mengisi setiap bidang dengan nilai defaultnya. Nilai boolean default salah, nilai integral default adalah 0.

Nilai default bilangan bulat menjadi 0 adalah masalah di sini karena Anda ingin bidang bilangan bulat menjadi -1 secara default. Anda bisa mendefinisikan tipe baru yang mengimplementasikan nilai default -1 dan menggunakannya sebagai ganti i64di struct Anda. (Saya belum mengujinya, tetapi seharusnya berhasil).

Namun, saya menyarankan untuk sedikit mengubah struktur dan penggunaan data Anda Option<i64>daripada i64. Saya tidak tahu konteks kode Anda, tetapi sepertinya Anda menggunakan nilai khusus -1 untuk mewakili arti khusus "tak terbatas", atau "tidak ada maks". Di Rust, kami menggunakan Optionuntuk mewakili nilai sekarang secara opsional. Tidak perlu meretas -1. Sebuah opsi dapat berupa salah satu Noneatau di Some(x)mana x akan menjadi milik Anda di i64sini. Bahkan mungkin bilangan bulat unsigned jika -1 adalah satu-satunya nilai negatif. Nilai defaultnya Optionadalah None, jadi dengan perubahan yang diajukan, kode Anda akan terlihat seperti ini:

#[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() };
Zargony
sumber
1
Terima kasih, saya telah membaca sekilas, tetapi saya akan membaca ulang untuk lebih memahami. Default "alami" yang digunakan beberapa bahasa seperti saya yakin nol, salah, "", dll., Akan cocok untuk saya. Saya mengerti bahwa ada implikasi yang lebih luas daripada "masalah" kecil saya untuk dipecahkan. Kemampuan untuk menyatakan misalnya. "iVal: i64 = 0", akan memenuhi kebutuhan saya yang lebih luas, tapi saya rasa itu tidak akan terjadi. The "# [deriving (Default)]" harus menyelesaikan sebagian besar keinginan saya. Saya tidak yakin mengapa saya menggunakan -1 dalam program pengujian saya, tetapi itu tidak diperlukan (historis). Akan sangat berguna (IMHO) untuk dapat menetapkan nilai di tempat di mana bidang tersebut ditentukan.
Brian Oh
9
@ BrianOh, secara tangensial, "nilai default untuk bidang struct" (yaitu sesuatu seperti struct Foo { val: i64 = 0 }) telah diusulkan dan mungkin muncul di versi yang lebih baru.
huon
Akan lebih baik jika itu diterapkan IMO - "struct foo {....". Saya membuat perubahan seperti yang disarankan oleh Anda, menggunakan struct seperti yang tertulis dalam pertanyaan saya dan dengan default. Itu pasti lebih cocok untuk saya dan jauh lebih ringkas. Karena tidak terbiasa dengan sintaks, satu masalah kecil yang saya alami adalah tidak mengetahui sintaks untuk SEMUA default. IE: Saya menggunakan "= cParams {iInsertMax: 10, ..Default :: default ()};", tetapi sebenarnya saya ingin "iInstanceMax" juga menjadi default. IMO akan lebih disukai untuk "# [deriving (Default)]" menjadi bagian dari struct, tapi saya kira alternatif lebih cocok untuk kompilator.
Brian Oh
2
Terima kasih banyak untuk itu. IMHO defaultnya harus default. YAITU. Menurut saya tidak perlu menentukan Default: default dll., Dll. Saya juga berpikir bahwa field harus dapat diberi nilai di mana mereka didefinisikan. Itu hanya dari perspektif saya yang sederhana, dan saya menyadari bahwa Rust dirancang agar aman, dan ada perspektif yang jauh lebih luas daripada saya. Ketika seseorang mempelajari bahasa (atau setidaknya saya), implementasi saat ini tampaknya sedikit rumit. Rust bukanlah bahasa IMHO yang sederhana, dan semakin banyak yang layak dilakukan untuk menyederhanakannya semakin baik setidaknya bagi saya.
Brian Oh
2
Apakah perlu menentukan default untuk semua bidang saat mengimplementasikan Defaultuntuk struct?
Matthew Stevenson