Hello.
I'm trying to pass functions as callbacks in rust, everything looks fine with normal functions.
#[derive(Debug, PartialEq)]
pub enum ExplainResult {
Integer(i32),
Float(f64),
}
fn people_explain_one_number(value: i32) -> ExplainResult {
ExplainResult::Integer(value)
}
fn people_explain_two_numbers(value: i32, value2: i32) -> ExplainResult {
ExplainResult::Float(value as f64 / value2 as f64)
}
fn dog_explain_one_number(value: i32) -> ExplainResult {
ExplainResult::Integer(value - 1)
}
fn dog_explain_two_numbers(value: i32, value2: i32) -> ExplainResult {
ExplainResult::Float(value as f64 / value2 as f64 - 1.0)
}
pub fn explain_by_people(key: &str) -> ExplainResult {
common_explain(key, people_explain_one_number, people_explain_two_numbers)
}
pub fn explain_by_dog(key: &str) -> ExplainResult {
common_explain(key, dog_explain_one_number, dog_explain_two_numbers)
}
fn common_explain(
key: &str,
explain_one_number: impl Fn(i32) -> ExplainResult,
explain_two_number: impl Fn(i32, i32) -> ExplainResult,
) -> ExplainResult {
match key {
"what is 1" => explain_one_number(1),
"what is 3 divide by 2" => explain_two_number(3, 2),
_ => ExplainResult::Integer(0),
}
}
But I'm struggling to make the impl functions async.
- when I passed only one function r, it works well.
use std::future::Future;
fn common_explain<Fut>(key: &str, explain_one_number: impl Fn(i32) -> Fut) -> Fut
where
Fut: Future<Output = ExplainResult>,
{
match key {
"what is 1" => explain_one_number(1),
_ => explain_one_number(0),
}
}
async fn people_explain_one_number(value: i32) -> ExplainResult {
ExplainResult::Integer(value)
}
pub async fn explain_by_people(key: &str) -> ExplainResult {
common_explain(key, people_explain_one_number).await
}
2.when I passed two functions as parameters, seems that the where
syntax does not work (Playground).
According to this thread, I kind of understand why. (because of the where
syntax is something like impl Trait
, which actually gives no explicit type, so the compiler thinks the two functions return different types? Please correct me if there are problems with my understanding.)
fn common_explain<Fut>(
key: &str,
explain_one_number: impl Fn(i32) -> Fut,
explain_two_number: impl Fn(i32, i32) -> Fut,
) -> Fut
where
Fut: Future<Output = ExplainResult>,
{
match key {
"what is 1" => explain_one_number(1),
"what is 3 divide by 2" => explain_two_number(3, 2),
_ => explain_one_number(0),
}
}
- so I'm trying to make the return type explicit. I have few experience in rust, in my experience, I should work with
Box
anddyn
. I find this post rust - How can one await a result of a boxed future? - Stack Overflow to useFuture
withBox
, but the code (Playground) produces some errors, and I have no clue to handle this.
fn common_explain(
key: &str,
explain_one_number: impl Fn(i32) -> dyn Future<Output = ExplainResult>,
explain_two_number: impl Fn(i32, i32) -> dyn Future<Output = ExplainResult>,
) -> Pin<Box<dyn Future<Output = ExplainResult>>> {
let explain_one_number = |value: i32| Box::pin(explain_one_number(value));
let explain_two_number = |value: i32, value2: i32| Box::pin(explain_two_number(value, value2));
match key {
"what is 1" => explain_one_number(1),
"what is 3 divide by 2" => explain_two_number(3, 2),
_ => explain_one_number(0),
}
}
here is a part of the error.
error[E0277]: the size for values of type `dyn Future<Output = ExplainResult>` cannot be known at compilation time
--> src/lib.rs:38:52
|
38 | let explain_one_number = |value: i32| Box::pin(explain_one_number(value));
| -------- ^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
| |
| required by a bound introduced by this call
|
= help: the trait `Sized` is not implemented for `dyn Future<Output = ExplainResult>`
note: required by a bound in `Box::<T>::pin`
Am I moving in the right direction to solve this problem?