Does Rust support closures with generic return types? For example, I want to write something like this:
let get = |s: &str| -> Opt
No, AFAIK you can't. I mean, you can define a generic closure, what you can't do is create a let binding with a generic left-hand side.
A fn get<T>
, as the one you mention rewriting, undergoes monomorphisation, i.e. when compiling it, rustc generates a different version of get
for every actual T
that is used to call it. By the time you assign the result of that get
(let a = get(...)
), that result has a concrete type and size.
A let
binding does not get monomorphised, so you can't have a let a<T> = ...
and have a different version of a
generated for you by the compiler.
What I think might enable this is the introduction of higher-kinded types, which is one of the highly desired but not yet fully fleshed out new features for Rust. They would enable you to write something like:
// does not work as of Rust 1
let a = for<T> |s: &str, t: T| {...}
i.e. return a closure that I can later parametrize with a T (which is what you're asking for).
The closure type is anonymous, so you won’t be able to write it down, and seems that the compiler won’t be able to infer it, so no luck.
But is there any particular reason you want to use a closure? If I understood your question correctly, you just use this function to factor out some repeating actions, and you are not actually going to pass it around. Thus, an inner fn
should work just fine. The downside is that you’ll have to pass all the values that used to be automatically captured by your closure.
It would be something like that (the example is still pretty complex, so I didn’t try to compile it):
fn from_row(result: &QueryResult, row: Vec<Value>) -> User {
let mut map: HashMap<_, _> = row.into_iter().enumerate().collect();
fn get<T: FromValue>(s: &str, result: &QueryResult, map: &mut HashMap<_, _>)
-> T {
result.column_index(s)
.and_then(|i| map.remove(&i))
.and_then(|x| from_value_opt(x)).ok()
};
User {
id: get("id", &result, &mut map)
}
}