Есть ли более быстрый / более короткий способ инициализировать переменные в структуре Rust?

103

В следующем примере я бы предпочел присвоить значение каждому полю в структуре в объявлении полей. В качестве альтернативы, для присвоения значений полям фактически требуется один дополнительный оператор для каждого поля. Все, что я хочу сделать, это назначать значения по умолчанию при создании экземпляра структуры.

Есть ли более лаконичный способ сделать это?

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,
        }
    }
}
Брайан О
источник

Ответы:

162

Вы можете предоставить значения по умолчанию для своей структуры, реализовав Defaultтрейт. defaultФункция будет выглядеть текущую newфункцию:

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

Затем вы можете создать экземпляр структуры, указав только значения, отличные от значений по умолчанию:

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

С некоторыми незначительными изменениями в структуре данных вы можете воспользоваться автоматически созданной реализацией по умолчанию. Если вы используете #[derive(Default)]структуру данных, компилятор автоматически создаст для вас функцию по умолчанию, которая заполняет каждое поле своим значением по умолчанию. Логическое значение по умолчанию - false, целое значение по умолчанию - 0.

Целочисленное значение по умолчанию, равное 0, представляет собой проблему, поскольку вы хотите, чтобы целочисленные поля были по умолчанию равны -1. Вы можете определить новый тип, который реализует значение по умолчанию -1, и использовать его вместо i64своей структуры. (Я не тестировал это, но он должен работать).

Однако я бы посоветовал немного изменить структуру данных и использовать Option<i64>вместо i64. Я не знаю контекста вашего кода, но похоже, что вы используете специальное значение -1 для представления специального значения «бесконечный» или «нет максимума». В Rust мы используем Optionопциональную приведенную стоимость. Нет необходимости в взломе -1. Вариант может быть либо здесь, Noneлибо Some(x)где x будет вашим i64здесь. Это могло бы быть даже целое число без знака, если бы -1 было единственным отрицательным значением. Значение по умолчанию Optionравно None, поэтому с предлагаемыми изменениями ваш код может выглядеть следующим образом:

#[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() };
Заргоны
источник
2
Спасибо, я быстро прочитал, но я перечитаю, чтобы лучше понять. "Естественные" значения по умолчанию, которые используются в некоторых языках, например, я считаю, что ноль, ложь, "" и т. Д., Подойдут мне. Я понимаю, что есть более широкие последствия, чем моя маленькая «проблема», которую нужно решить. Возможность заявить напр. «iVal: i64 = 0» решит мои более широкие потребности, но я думаю, этого не произойдет. «# [Deriving (Default)]» должно решить большинство моих проблем. Я не уверен, почему я использовал -1 в своей тестовой программе, но это не нужно (исторически). Было бы очень полезно (IMHO) иметь возможность назначать значение на месте, где определено поле.
Брайан О
9
@BrianOh, попутно, были предложены «значения по умолчанию для полей структуры» (т.е. что-то вроде struct Foo { val: i64 = 0 }), которые могут появиться в более поздних версиях.
huon
Было бы хорошо, если бы это было реализовано IMO - "struct foo {....". Я внес изменения, как предложено вами, используя структуру, как написано в моем вопросе, и значение по умолчанию. Это, безусловно, мне больше подходит и гораздо более лаконично. Поскольку я был незнаком с синтаксисом, одна небольшая проблема заключалась в том, что я не знал синтаксиса для ВСЕХ значений по умолчанию. IE: я использовал "= cParams {iInsertMax: 10, ..Default :: default ()};", но на самом деле я хочу, чтобы iInstanceMax также был значением по умолчанию. IMO было бы предпочтительнее, чтобы «# [deriving (Default)]» было частью структуры, но я думаю, что альтернатива лучше подходит для компилятора.
Брайан О
2
Большое спасибо за это. IMHO значения по умолчанию должны быть по умолчанию. IE. Я не думаю, что необходимо указывать Default: default и т. Д. И т. Д. Я также считаю, что полям должно быть присвоено значение там, где они определены. Это просто с моей точки зрения, и я понимаю, что Rust разработан для обеспечения безопасности, и что существует гораздо более широкая перспектива, чем моя. Когда кто-то изучает язык (или, по крайней мере, меня), текущая реализация кажется немного громоздкой. ИМХО, Rust - не простой язык, и чем больше можно сделать для его упрощения, тем лучше для меня, по крайней мере.
Брайан О
4
Необходимо ли при реализации Defaultструктуры определять значения по умолчанию для всех полей ?
Мэтью Стивенсон