Идиоматический способ создания статической повторяющейся коллекции именованных структур?

#data-structures #rust

#структуры данных #Ржавчина

Вопрос:

Каков идиоматический способ создания статической повторяющейся коллекции именованных структур? У меня есть n экземпляры структуры, где n известно во время компиляции и их меньше 20. Я хотел бы иметь возможность выполнять итерации по всем записям, а также иметь возможность ссылаться на каждую запись по имени вместо индекса. Все данные известны во время компиляции.

Я мог бы использовать массив или перечисление вместе с написанными от руки константами, которые сопоставляют метки с индексами; но это кажется сложным.

 fn common_behaviour(x: f64) {
   print!("{}", x);
}

const ADD: usize = 0;
const SUBTRACT: usize = 1;

fn main () {
    let mut foos: [f64; 2] = [0.0; 2];
    foos[ADD] = 4.0;
    foos[SUBTRACT] = 2.0;

    for foo in amp;foos {
       common_behaviour(*foo);
    }
    foos[ADD]  = 1.0;
    foos[SUBTRACT] -= 1.0;
}

  

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

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

 fn common_behaviour(x: f64) {
   print!("{}", x);
}

fn add(x: f64) -> f64 {
    x   1.0
}

fn subtract(x: f64) -> f64 {
    x - 1.0
}

struct Foo {
   data: f64,
   special: fn(f64) -> f64
}

impl Foo {
    fn new(data: f64, special: fn(f64) -> f64) -> Foo {
        Foo { data, special }
    }
}

fn main() {
    let mut foos = [Foo::new(4.0, add), Foo::new(2.0, subtract)];

    for foo in amp;mut foos {
       common_behaviour(foo.data);
       foo.data = (foo.special)(foo.data);
    }
}
  

Какой наиболее идиоматичный способ справиться с этой ситуацией?

Комментарии:

1. Проверьте rust-phf на наличие карт, сгенерированных во время компиляции.

2. Этому вопросу мог бы помочь пример кода, показывающий, что у вас есть и как вы это используете; я понятия не имею, что делать с комментарием «указатели на функции», он кажется не связанным с проблемой … что заставляет меня думать, что я не понял проблему с самого начала.

3. @MatthieuM. Добавлены примеры кода. Если вам нужно больше разъяснений, я с радостью их добавлю.

Ответ №1:

Глядя на:

 fn main() {
    let mut foos = [Foo::new(4.0, add), Foo::new(2.0, subtract)];

    for foo in amp;mut foos {
       common_behaviour(foo.data);
       foo.data = (foo.special)(foo.data);
    }
}
  

Я вижу, что шаблон команд изо всех сил пытается появиться, и Rust великолепен в выражении этого шаблона, благодаря enum :

 enum Foo {
    Add(f64),
    Sub(f64),
}

impl Foo {
    fn apply(amp;mut self) {
        match self {
            Foo::Add(x) => {
                Self::common(*x);
                *x  = 1.0;
            },
            Foo::Sub(x) => {
                Self::common(*x);
                *x -= 1.0;
            },
        }
    }

    fn common(x: f64) {
        print!("{}", x);
    }
}
  

И ваш пример становится:

 fn main() {
    let mut foos = [Foo::Add(4.0), Foo::Sub(2.0)];

    for foo in amp;mut foos {
       foo.apply();
    }
}