Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

type erasure for functions in rust

Tags:

c++

rust

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?

like image 864
skgbanga Avatar asked Apr 20 '21 16:04

skgbanga


People also ask

Does rust have type erasure?

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!

What are The unsized types in rust?

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:

What is the use of non_exhaustive feature in rust?

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.

What are tool attributes in rustc?

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.


1 Answers

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.

like image 170
Ivan C Avatar answered Oct 08 '22 13:10

Ivan C