Вы можете начать с этого:
fn with_consumer_function<DS: Dataset>(
optional: Option<DS>,
consumer: impl FnOnce(DS) -> Result<(), Box<dyn Error>>,
) -> Result<(), Box<dyn Error>> {
match optional {
Some(dataset) => consumer(dataset),
None => todo!(), //consumer(static_dataset()),
}
}
Если вы хотите изменить руку None
, вам нужно будет создать метод (generi c) для создания набора данных. Вы можете сделать это, расширив черту Dataset
с помощью fn static_dataset() -> Self
.
Причина, по которой None
не работает с замыканием, заключается в том, что ржавчина (по крайней мере, на данный момент) рассматривает замыкания как принятие исправленных параметры. Если consumer
принимает DS
в первой ветви, он не может просто принимать HashMap
во второй - он все равно должен принимать тот же тип: DS
.
Вы можете обойти это, определив ваша собственная черта:
trait DatasetConsumer {
fn call<DS: Dataset>(self, ds: DS) -> Result<(), Box<dyn Error>>;
}
struct DatasetConsumerRun;
impl DatasetConsumer for DatasetConsumerRun {
fn call<DS: Dataset>(self, mut dataset: DS) -> Result<(), Box<dyn Error>> {
println!("{}", dataset.read("info.txt")?);
Ok(())
}
}
fn with_consumer_function<DS: Dataset>(
optional: Option<DS>,
consumer: impl DatasetConsumer,
) -> Result<(), Box<dyn Error>> {
match optional {
Some(dataset) => consumer.call(dataset),
None => consumer.call(static_dataset()),
}
}
fn main() -> Result<(), Box<dyn Error>> {
let optional = Some(PathBuf::from("/path/to/dataset/.txt"));
with_consumer_function(optional.clone(), DatasetConsumerRun)?;
Ok(())
}
Тем не менее, использовать DatasetConsumer
труднее, чем использовать простые замыкания.
Вы также можете попробовать реализовать with_consumer_function
как макрос, но я не уверен, что пойду по этому пути.