#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();
}
}