Gibt es eine schnellere / kürzere Möglichkeit, Variablen in einer Rust-Struktur zu initialisieren?

101

Im folgenden Beispiel würde ich es vorziehen, jedem Feld in der Struktur in der Deklaration der Felder einen Wert zuzuweisen. Alternativ ist effektiv eine zusätzliche Anweisung für jedes Feld erforderlich, um den Feldern einen Wert zuzuweisen. Alles, was ich tun möchte, ist, Standardwerte zuzuweisen, wenn die Struktur instanziiert wird.

Gibt es einen prägnanteren Weg, dies zu tun?

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
quelle

Antworten:

160

Sie können Standardwerte für Ihre Struktur angeben, indem Sie das DefaultMerkmal implementieren . Die defaultFunktion würde wie Ihre aktuelle newFunktion aussehen :

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

Sie können die Struktur dann instanziieren, indem Sie nur die nicht standardmäßigen Werte angeben:

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

Mit einigen geringfügigen Änderungen an Ihrer Datenstruktur können Sie eine automatisch abgeleitete Standardimplementierung nutzen. Wenn Sie #[derive(Default)]eine Datenstruktur verwenden, erstellt der Compiler automatisch eine Standardfunktion für Sie, die jedes Feld mit seinem Standardwert füllt. Der Standard-Boolesche Wert ist false, der Standard-Integralwert ist 0.

Der Standardwert einer Ganzzahl von 0 ist hier ein Problem, da die Ganzzahlfelder standardmäßig -1 sein sollen. Sie können einen neuen Typ definieren, der einen Standardwert von -1 implementiert, und diesen anstelle i64Ihrer Struktur verwenden. (Ich habe das nicht getestet, aber es sollte funktionieren).

Ich würde jedoch vorschlagen, Ihre Datenstruktur geringfügig zu ändern und Option<i64>stattdessen zu verwenden i64. Ich kenne den Kontext Ihres Codes nicht, aber es sieht so aus, als würden Sie den speziellen Wert -1 verwenden, um die spezielle Bedeutung "unendlich" oder "es gibt kein Maximum" darzustellen. In Rust verwenden wir a Option, um einen optional vorhandenen Wert darzustellen. Es ist kein -1-Hack erforderlich. Eine Option kann entweder sein Noneoder Some(x)wo x Ihr i64hier sein würde. Es könnte sogar eine Ganzzahl ohne Vorzeichen sein, wenn -1 der einzige negative Wert wäre. Der Standardwert Optionist None. Mit den vorgeschlagenen Änderungen könnte Ihr Code folgendermaßen aussehen:

#[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
quelle
1
Danke, ich hatte eine schnelle Lektüre, aber ich werde sie noch einmal lesen, um sie besser zu verstehen. Die "natürlichen" Standardeinstellungen, die einige Sprachen verwenden, wie ich glaube, Null, Falsch usw., würden mir passen. Ich verstehe, dass es weitreichendere Implikationen gibt als mein kleines "Problem" zu lösen. Aussagefähigkeit zB. "iVal: i64 = 0" würde meine umfassenderen Anforderungen lösen, aber ich denke, das wird nicht passieren. Das "# [Ableiten (Standard)]" sollte die meisten meiner Wünsche lösen. Ich bin mir nicht sicher, warum ich -1 in meinem Testprogramm verwendet habe, aber es wird nicht benötigt (historisch). Es wäre sehr nützlich (IMHO), in situ einen Wert zuweisen zu können, in dem das Feld definiert ist.
Brian Oh
9
@BrianOh, tangential, wurden die "Standardwerte für Strukturfelder" (dh so etwas wie struct Foo { val: i64 = 0 }) vorgeschlagen und können daher in späteren Versionen erscheinen.
Huon
Es wäre gut, wenn das implementiert wäre IMO - "struct foo {....". Ich habe die von Ihnen vorgeschlagenen Änderungen unter Verwendung der in meiner Frage beschriebenen Struktur und mit der Standardeinstellung vorgenommen. Das passt mir sicherlich besser und ist viel prägnanter. Da ich mit der Syntax nicht vertraut war, bestand ein kleines Problem darin, die Syntax für ALLE Standardeinstellungen nicht zu kennen. IE: Ich habe "= cParams {iInsertMax: 10, ..Default :: default ()};" verwendet, aber ich möchte eigentlich, dass "iInstanceMax" auch ein Standard ist. IMO wäre es vorzuziehen, wenn "# [ableiving (Default)]" Teil der Struktur ist, aber ich denke, die Alternative passt besser zum Compiler.
Brian Oh
2
Vielen Dank dafür. IMHO sollten die Standardeinstellungen die Standardeinstellungen sein. IE. Ich denke nicht, dass es notwendig sein sollte, Standard anzugeben: Standard usw. usw. Ich denke auch, dass den Feldern ein Wert zugewiesen werden kann, in dem sie definiert sind. Das ist nur aus meiner einfachen Perspektive und ich erkenne, dass Rust so konzipiert ist, dass es sicher ist und dass es eine viel breitere Perspektive gibt als meine. Wenn man die Sprache lernt (oder zumindest ich), scheint die aktuelle Implementierung etwas umständlich zu sein. Rust ist meiner Meinung nach keine einfache Sprache, und je mehr getan werden kann, um sie zu vereinfachen, desto besser für mich.
Brian Oh
2
Müssen bei der Implementierung Defaultfür eine Struktur Standardeinstellungen für alle Felder definiert werden ?
Matthew Stevenson