¿Existe una forma más rápida/corta de inicializar variables en una estructura de Rust?

Resuelto Brian Oh asked hace 11 años • 2 respuestas

En el siguiente ejemplo, preferiría asignar un valor a cada campo en la estructura en la declaración de los campos. Alternativamente, efectivamente se necesita una declaración adicional para cada campo para asignar un valor a los campos. Todo lo que quiero poder hacer es asignar valores predeterminados cuando se crea una instancia de la estructura.

¿Existe una forma más sucinta de hacer esto?

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 avatar Oct 29 '13 12:10 Brian Oh
Aceptado

Puede proporcionar valores predeterminados para su estructura implementando el Defaultrasgo. La defaultfunción se parecería a su newfunción actual:

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

Luego puede crear una instancia de la estructura proporcionando solo los valores no predeterminados:

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

Con algunos cambios menores en su estructura de datos, puede aprovechar una implementación predeterminada derivada automáticamente. Si lo usa #[derive(Default)]en una estructura de datos, el compilador creará automáticamente una función predeterminada que llena cada campo con su valor predeterminado. El valor booleano predeterminado es falso, el valor integral predeterminado es 0.

El valor predeterminado de un número entero que es 0 es un problema aquí ya que desea que los campos de números enteros sean -1 de forma predeterminada. Podría definir un nuevo tipo que implemente un valor predeterminado de -1 y usarlo en lugar de i64en su estructura. (No lo he probado, pero debería funcionar).

Sin embargo, sugeriría cambiar ligeramente la estructura de datos y usar Option<i64>en lugar de i64. No conozco el contexto de tu código, pero parece que estás usando el valor especial de -1 para representar el significado especial "infinito" o "no hay máximo". En Rust, usamos an Optionpara representar un valor presente opcionalmente. No es necesario un truco de -1. Una opción puede ser Noneo Some(x)donde x estaría i64aquí. Incluso podría ser un entero sin signo si -1 fuera el único valor negativo. OptionEl valor predeterminado es None, por lo que con los cambios propuestos, su código podría verse así:

#[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 avatar Oct 29 '2013 08:10 Zargony

Hoy en día, es posible hacer exactamente lo que OP pedía hace 8 años.

para asignar un valor a cada campo en la estructura en la declaración de los campos.

usando caja derivada :

#![allow(non_snake_case)]
#![allow(non_camel_case_types)]

use derivative::Derivative;

#[derive(Derivative)]
#[derivative(Debug, Default)]
struct cParams {
    #[derivative(Default(value = "-1"))]
    iInsertMax: i64,
    #[derivative(Default(value = "-1"))]
    iUpdateMax: i64,
    #[derivative(Default(value = "-1"))]
    iDeleteMax: i64,
    #[derivative(Default(value = "-1"))]
    iInstanceMax: i64,
    #[derivative(Default(value = "false"))]
    tFirstInstance: bool,
    #[derivative(Default(value = "false"))]
    tCreateTables: bool,
    #[derivative(Default(value = "false"))]
    tContinue: bool,
}

fn main() {
    println!("cParams: {:?}", cParams::default());
}

Además, no es necesario definir valores falsos predeterminados para los valores booleanos de esta manera porque Defaultlos establecerá en este valor de todos modos.

SET001 avatar Sep 19 '2021 06:09 SET001