Consider this C++ code:
#include <iostream>
#include <functional>
using namespace std;
std::function<int(int, int)> foo(int c) {
auto add = [] (int a, int b) { return a + b; };
auto sub = [] (int a, int b) { return a - b; };
if (c > 42) {
return add;
} else {
return sub;
}
}
int main() {
cout << foo(100)(10, 20) << '\n';
}
Both lambdas (add
and sub
) are type erased via std::function
and that function is then called in main.
I am wondering how can I replicate this pattern in rust?
Rust does have type erasure in the form of virtual method dispatch via dyn Trait, which allows you to have a Vec where the elements have different concrete types: fn main () { let list: Vec<Box<dyn ToString>> = vec!
In Rust, there are two Unsized types: Slice and Trait. These Unsized types use fat pointers to reference the underlying object. The C-ABI compatible for fat pointer layout is like below:
feature — Used to enable unstable or experimental compiler features. See The Unstable Book for features implemented in rustc. non_exhaustive — Indicate that a type will have more fields/variants added in future.
When the tool is in use, the tool is responsible for processing and interpretation of its attributes. Tool attributes are not available if the no_implicit_prelude attribute is used. Note: rustc currently recognizes the tools "clippy" and "rustfmt". The following is an index of all built-in attributes. cfg — Controls conditional compilation.
A rather exact translation of your example would be the following snippet.
fn foo(c: i32) -> Box<dyn Fn(i32, i32) -> i32> {
let add = |a, b| a + b;
let sub = |a, b| a - b;
Box::new(if c > 42 { add } else { sub })
}
fn main() {
println!("{}", foo(100)(10, 20));
}
A type of closure is unnameable, so we coerce it to a trait object and store it on the heap, which is as far as I understand, is about the same thing std::function
does.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With