C'è un modo più veloce / più breve per inizializzare le variabili in una struttura Rust?


102

Nell'esempio seguente, preferirei di gran lunga assegnare un valore a ciascun campo nella struttura nella dichiarazione dei campi. In alternativa, è effettivamente necessaria un'istruzione aggiuntiva per ogni campo per assegnare un valore ai campi. Tutto quello che voglio essere in grado di fare è assegnare valori predefiniti quando viene istanziata la struttura.

C'è un modo più succinto per farlo?

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,
        }
    }
}

Risposte:


162

Puoi fornire valori predefiniti per la tua struttura implementando il Defaulttratto. La defaultfunzione sarebbe simile alla tua newfunzione attuale :

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

È quindi possibile istanziare la struttura fornendo solo i valori non predefiniti:

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

Con alcune piccole modifiche alla struttura dei dati, è possibile trarre vantaggio da un'implementazione predefinita derivata automaticamente. Se usi #[derive(Default)]una struttura dati, il compilatore creerà automaticamente una funzione predefinita per te che riempie ogni campo con il suo valore predefinito. Il valore booleano predefinito è false, il valore integrale predefinito è 0.

Il valore predefinito di un intero che è 0 è un problema qui poiché si desidera che i campi interi siano -1 per impostazione predefinita. Potresti definire un nuovo tipo che implementa un valore predefinito di -1 e usarlo invece che i64nella tua struttura. (Non l'ho testato, ma dovrebbe funzionare).

Tuttavia, suggerirei di modificare leggermente la struttura dei dati e utilizzare Option<i64>invece di i64. Non conosco il contesto del tuo codice, ma sembra che tu stia usando il valore speciale di -1 per rappresentare il significato speciale "infinito" o "non c'è massimo". In Rust, usiamo un Optionper rappresentare un valore presente facoltativamente. Non è necessario un hack -1. Un'opzione può essere Noneo Some(x)dove x sarebbe la tua i64qui. Potrebbe anche essere un numero intero senza segno se -1 fosse l'unico valore negativo. Il Optionvalore predefinito è None, quindi con le modifiche proposte, il codice potrebbe essere simile a questo:

#[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
Grazie, ho avuto una lettura veloce, ma rileggerò per capire meglio. Le impostazioni predefinite "naturali" utilizzate da alcuni linguaggi, come credo zero, false, "", ecc., Mi andrebbero bene. Capisco che ci sono implicazioni più ampie da risolvere rispetto al mio piccolo "problema". Capacità di affermare ad es. "iVal: i64 = 0", risolverebbe le mie esigenze più ampie, ma immagino che non accadrà. Il "# [derivante (predefinito)]" dovrebbe risolvere la maggior parte delle mie esigenze. Non sono sicuro del motivo per cui ho usato -1 nel mio programma di test, ma non è necessario (storico). Sarebbe molto utile (IMHO) poter assegnare un valore in situ dove è definito il campo.
Brian Oh

9
@BrianOh, tangenzialmente, struct Foo { val: i64 = 0 }sono stati proposti i "valori di default per i campi struct" (cioè qualcosa di simile ) e quindi potrebbero apparire nelle versioni successive.
huon

Sarebbe bello se fosse implementato IMO - "struct foo {....". Ho apportato le modifiche come suggerito da te, utilizzando la struttura come scritto nella mia domanda e con l'impostazione predefinita. Questo mi sta sicuramente meglio ed è molto più conciso. Non avendo familiarità con la sintassi, un problema minore che ho avuto è stato non conoscere la sintassi per TUTTE le impostazioni predefinite. IE: ho usato "= cParams {iInsertMax: 10, ..Default :: default ()};", ma in realtà voglio che "iInstanceMax" sia anche un valore predefinito. IMO sarebbe preferibile che "# [deriving (Default)]" facesse parte della struttura, ma immagino che l'alternativa si adatti meglio al compilatore.
Brian Oh

2
Molte grazie per questo. IMHO le impostazioni predefinite dovrebbero essere quelle predefinite. IE. Non penso che dovrebbe essere necessario specificare Default: default ecc., Ecc. Penso anche che ai campi dovrebbe essere possibile assegnare un valore dove sono definiti. Questo è solo dalla mia semplice prospettiva, e mi rendo conto che Rust è progettato per essere sicuro e che esiste una prospettiva molto più ampia della mia. Quando si impara la lingua (o almeno io), l'implementazione corrente sembra un po 'macchinosa. Rust non è un semplice linguaggio IMHO, e più si può fare per semplificarlo meglio è per me.
Brian Oh

2
È necessario definire i valori predefiniti per tutti i campi durante l'implementazione Defaultper una struttura?
Matthew Stevenson
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.