I'm starting with Rust and trying to implement a struct like the following, where I have a vector of predicate functions:
pub struct Client<P>
where
P: Fn(&Deal) -> bool,
{
clientid: String,
api_url: String,
deal_filters: Vec<P>,
}
I managed to cobble this together based on various things, and I was previously able to implement a new
function for these structs when I just hard-code this attribute to an empty vector, but it gets weird when I try construct one of these with real functions:
impl<P> Client<P>
where
P: Fn(&Deal) -> bool,
{
pub fn new(stings: settings::Settings, filters: Option<Vec<P>>) -> Self {
let deal_filters = match filters {
Some(fltrs) => fltrs,
None => vec![deal_predicates::check_revenue],
};
Self {
api_url: stings.url,
clientid: stings.clientid,
deal_filters
}
}
Indeed, when I try to pass these "default" filters in, I get the following compiler error:
`match` arms have incompatible types
expected type `Vec<for<'r> fn(&'r Deal) -> _>`
found struct `Vec<for<'r> fn(&'r Deal) -> _ {check_revenue}>`rustcE0308
In addition, I'm not sure how to declare the type for an instance. I'm unclear on the type
I am declaring this Client<P>
to be.
The following is based on trying to follow guidance from the compiler, but it's telling me that the size can't be known at compile time:
let client: clients::Client<dyn Fn(&Deal) -> bool>
= clients::Client::new(cfg, None);
14 | = client: clients::Client::new(cfg, None);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
My goal was to provide a set of predicate functions that can be used and offer different predicates for different contexts. I believe I could potentially use Box
to solve the "size can't be known at compile time" problem?
Of course, there are certainly other ways I can solve this problem. In addition, a lot of my thinking about this is based on Haskell, so I probably have the wrong expectations or assumptions here, but I would appreciate suggestions as to a better way to achieve what I want.
Edit: Fixed Version Below
Thanks to some help below, I wrapped up my functions in Box
and then my new problem was the error expected fn pointer, found reference
. I also simplified it to remove the generic trait declaration.
Once I googled and resolved the expected fn pointer, found reference
error, my code compiled fine. This solution is unfamiliar to me, so I am unsure if it's idiomatic, but it seems to work.
Struct:
pub struct Client {
clientid: String,
api_url: String,
deal_filters: Vec<fn(&Deal) -> bool>,
}
impl new:
impl Client {
pub fn new(
stings: settings::Settings,
filters: Option<Vec<fn(&Deal) -> bool>>,
) -> Self {
let deal_filters = match filters {
Some(fltr) => fltr,
None => vec![
deal_predicates::check_revenue as fn(&Deal) -> bool,
],
};
Self {
api_url: stings.url,
clientid: stings.clientid,
deal_filters,
}
}
}
I also got it working with Box
ing the dyn Fn(&Deal) -> bool
types.