How can I iterate over a vector of functions and call each of them? - rust

I'm trying to use a for loop to iterate over a vector of functions and execute each function at each step.
fn f1(i: i32) -> i32 {
i * 2
}
fn f2(i: i32) -> i32 {
i * 4
}
fn main() {
let mut arr: Vec<|i32| -> i32> = Vec::new();
arr.push(f1);
arr.push(f2);
for f in arr.iter() {
println!("{}", f(1));
}
}
But the attempted execution of f(1) gives this error:
error: expected function, found '&|i32| -> i32'
I guess in putting the functions in the vector their type is mutated and no longer works like a normal function. Is there a way to transform it back, or am I missing something?

As of Rust 1.x, unboxed closures are the only kind of closures in the language, and they don't need a feature flag. Moreover, static functions can easily be converted to unboxed closures. Therefore, the correct way to call functions from a vector of functions is:
fn f1(i: i32) -> i32 { i * 2 }
fn f2(i: i32) -> i32 { i * 4 }
fn main() {
let arr: Vec<&dyn Fn(i32) -> i32> = vec![&f1, &f2];
for f in &arr {
println!("{}", (f)(1));
}
}
I've used Fn() closures which can access their environment through a shared reference, so it is sufficient to iterate the vector by reference. If I had used a FnMut() closure, I would have had to use iteration by mutable reference:
fn f1(i: i32) -> i32 { i * 2 }
fn f2(i: i32) -> i32 { i * 4 }
fn main() {
let p1 = &mut f1;
let p2 = &mut f2;
let mut arr: Vec<&mut dyn FnMut(i32) -> i32> = vec![p1, p2];
for f in &mut arr {
println!("{}", (f)(1));
}
}
A similar idea holds for FnOnce() and iteration by value, although here we need to use Box to own the closure:
fn f1(i: i32) -> i32 { i * 2 }
fn f2(i: i32) -> i32 { i * 4 }
fn main() {
let arr: Vec<Box<dyn FnOnce(i32) -> i32>> = vec![Box::new(f1), Box::new(f1)];
for f in arr {
println!("{}", (f)(1));
}
}
Alternatively, if you know that you only work with static functions, it is possible to store pointers to them directly, without using closure traits:
fn f1(i: i32) -> i32 { i * 2 }
fn f2(i: i32) -> i32 { i * 4 }
fn main() {
let arr: Vec<fn(i32) -> i32> = vec![f1, f2];
for f in &arr {
println!("{}", (f)(1));
}
}
While f1 and f2 actually have different incompatible types, they are automatically coerced to the general function pointer type fn(i32) -> i32 when used in appropriate context, like in the example above.
Because static functions don't have any environment, you can freely clone references to them and call them through any kind of reference. This is probably the way to go if you only need static functions.
This answer was updated for Rust 1.x; older versions of the answer remain in the edit history.

Related

how to create link on function in arguments in rust? [duplicate]

Can I pass a function as a parameter? If not, what is a good alternative?
I tried some different syntaxes but I have not found the right one. I know I can do this:
fn example() {
let fun: fn(value: i32) -> i32;
fun = fun_test;
fun(5i32);
}
fn fun_test(value: i32) -> i32 {
println!("{}", value);
value
}
but that's not passing the function as a parameter to another function:
fn fun_test(value: i32, (some_function_prototype)) -> i32 {
println!("{}", value);
value
}
Sure you can:
fn fun_test(value: i32, f: &dyn Fn(i32) -> i32) -> i32 {
println!("{}", f(value));
value
}
fn times2(value: i32) -> i32 {
2 * value
}
fn main() {
fun_test(5, &times2);
}
As this is Rust, you have to take into account the ownership and lifetime of the closure.
TL;DR; Basically there are 3 types of closures (callable objects):
Fn: It cannot modify the objects it captures.
FnMut: It can modify the objects it captures.
FnOnce: The most restricted. Can only be called once because when it is called it consumes itself and its captures.
See When does a closure implement Fn, FnMut and FnOnce? for more details
If you are using a simple pointer-to-function like closure, then the capture set is empty and you have the Fn flavor.
If you want to do more fancy stuff, then you will have to use lambda functions.
In Rust there are proper pointers to functions, that work just like those in C. Their type is for example fn(i32) -> i32. The Fn(i32) -> i32, FnMut(i32) -> i32 and FnOnce(i32) -> i32 are actually traits. A pointer to a function always implements all three of these, but Rust also has closures, that may or may not be converted to pointers (depending on whether the capture set is empty) to functions but they do implement some of these traits.
So for example, the example from above can be expanded:
fn fun_test_impl(value: i32, f: impl Fn(i32) -> i32) -> i32 {
println!("{}", f(value));
value
}
fn fun_test_dyn(value: i32, f: &dyn Fn(i32) -> i32) -> i32 {
println!("{}", f(value));
value
}
fn fun_test_ptr(value: i32, f: fn(i32) -> i32) -> i32 {
println!("{}", f(value));
value
}
fn times2(value: i32) -> i32 {
2 * value
}
fn main() {
let y = 2;
//static dispatch
fun_test_impl(5, times2);
fun_test_impl(5, |x| 2*x);
fun_test_impl(5, |x| y*x);
//dynamic dispatch
fun_test_dyn(5, &times2);
fun_test_dyn(5, &|x| 2*x);
fun_test_dyn(5, &|x| y*x);
//C-like pointer to function
fun_test_ptr(5, times2);
fun_test_ptr(5, |x| 2*x); //ok: empty capture set
fun_test_ptr(5, |x| y*x); //error: expected fn pointer, found closure
}
Fn, FnMut and FnOnce, outlined in the other answer, are closure types. The types of functions that close over their scope.
Apart from passing closures Rust also supports passing simple (non-closure) functions, like this:
fn times2(value: i32) -> i32 {
2 * value
}
fn fun_test(value: i32, f: fn(i32) -> i32) -> i32 {
println!("{}", f (value));
value
}
fn main() {
fun_test (2, times2);
}
fn(i32) -> i32 here is a function pointer type.
If you don't need a full-fledged closure than working with function types is often simpler as it doesn't have to deal with those closure lifetime nicities.

Determine fn output type from input type

I would like a function that returns f32 if the input is f32, for all other numeric inputs it should return f64.
A simplified example of the structure is this:
use num::{Num, NumCast, ToPrimitive, traits::Float};
fn example<N: Num + ToPrimitive, T: Float>(input: N) -> T {
let output = input + N::one();
NumCast::from(output).unwrap()
}
fn main() {
println!("{}", example::<f32, f32>(1f32));
println!("{}", example::<u32, f64>(1u32));
}
is there a way to control the dispatch so that I can drop the turbofish and it will automatically map
f32 -> f32 and
anything else -> f64 ?
You cannot have a function which returns either f32 or f64 making decision in runtime. But you can implement such behavior using traits.
You can have two traits ToF32 and ToF64 and implement first one for f32 only and ToF64 for all other numeric types except f32. You will need a lot of boilerplate code to implement ToF64 though. It can be compacted using macros.
use num::{NumCast, ToPrimitive, one, Integer};
trait ToF32 {
fn example(self) -> f32;
}
impl ToF32 for f32 {
fn example(self) -> f32 {
let output = self + one::<Self>();
NumCast::from(output).unwrap()
}
}
trait ToF64 {
fn example(self) -> f64;
}
impl<T: Integer + ToPrimitive> ToF64 for T {
fn example(self) -> f64 {
let output = self + one::<Self>();
NumCast::from(output).unwrap()
}
}
fn main() {
println!("{}", 1f32.example());
println!("{}", 1u32.example());
}
Playground link

Taking ownership of vector twice

I am trying to figure out the best way to use two functions on the same vector? I'm able to get both functions to do what I need them to do but as soon as I want to use them both on the same vector, I can't seem to make that compile "reasonably". I imagine I can just stick a bunch of muts and &s everywhere but that seems like a lot just to get two functions to run on the same vector as opposed to one. Am I missing some best practice here that can make this simpler?
Current code that fails compilation with v is a `&` reference error:
fn main() {
let vec = vec![1,2,1,4,5];
println!("Mean: {}, Median: {}", mean(&vec), median(&vec))
}
fn mean(v: &Vec<i32>) -> i32 {
v.iter().sum::<i32>() / v.len() as i32
}
fn median(v: &Vec<i32>) -> i32 {
v.sort();
let med_idx = v.len() / 2 as usize;
v[med_idx]
}
You cannot do that. Rust requires you to think about ownership and constness very deeply. For example, your median function seems to sort vector internally: you should either allow it to modify the argument passed (median(v: &mut Vec<i32>) in the function definition and &mut v in the argument) or make a copy explicitly inside. However, if you allow mutating the vector, the original vector should be mutable itself (let mut vec). So, you can hack your way through like this:
fn main() {
let mut vec = vec![1,2,1,4,5]; // !
println!("Mean: {}, Median: {}", mean(&vec), median(&mut vec)) // !
}
fn mean(v: &Vec<i32>) -> i32 {
v.iter().sum::<i32>() / v.len() as i32
}
fn median(v: &mut Vec<i32>) -> i32 { // !
v.sort();
let med_idx = v.len() / 2 as usize;
v[med_idx]
}
However, making median modify the vector it analyzes seems very weird to me. I think it would be better to make an explicit copy and sorting it:
fn main() {
let vec = vec![1,2,1,4,5];
println!("Mean: {}, Median: {}", mean(&vec), median(&vec))
}
fn mean(v: &Vec<i32>) -> i32 {
v.iter().sum::<i32>() / v.len() as i32
}
fn median(v: &Vec<i32>) -> i32 { // !
let v_sorted = v.sorted(); // creates a copy
let med_idx = v.len() / 2 as usize;
v[med_idx]
}
If you don't want the penalty, you can stick with the first solution and just create a copy on call site. This gives the most flexibility:
fn main() {
let vec = vec![1,2,1,4,5];
println!("Mean: {}, Median: {}", mean(&vec), median(&mut vec.clone())) // !
}
fn mean(v: &Vec<i32>) -> i32 {
v.iter().sum::<i32>() / v.len() as i32
}
fn median(v: &mut Vec<i32>) -> i32 { // !
v.sort();
let med_idx = v.len() / 2 as usize;
v[med_idx]
}

How do you pass a Rust function as a parameter?

Can I pass a function as a parameter? If not, what is a good alternative?
I tried some different syntaxes but I have not found the right one. I know I can do this:
fn example() {
let fun: fn(value: i32) -> i32;
fun = fun_test;
fun(5i32);
}
fn fun_test(value: i32) -> i32 {
println!("{}", value);
value
}
but that's not passing the function as a parameter to another function:
fn fun_test(value: i32, (some_function_prototype)) -> i32 {
println!("{}", value);
value
}
Sure you can:
fn fun_test(value: i32, f: &dyn Fn(i32) -> i32) -> i32 {
println!("{}", f(value));
value
}
fn times2(value: i32) -> i32 {
2 * value
}
fn main() {
fun_test(5, &times2);
}
As this is Rust, you have to take into account the ownership and lifetime of the closure.
TL;DR; Basically there are 3 types of closures (callable objects):
Fn: It cannot modify the objects it captures.
FnMut: It can modify the objects it captures.
FnOnce: The most restricted. Can only be called once because when it is called it consumes itself and its captures.
See When does a closure implement Fn, FnMut and FnOnce? for more details
If you are using a simple pointer-to-function like closure, then the capture set is empty and you have the Fn flavor.
If you want to do more fancy stuff, then you will have to use lambda functions.
In Rust there are proper pointers to functions, that work just like those in C. Their type is for example fn(i32) -> i32. The Fn(i32) -> i32, FnMut(i32) -> i32 and FnOnce(i32) -> i32 are actually traits. A pointer to a function always implements all three of these, but Rust also has closures, that may or may not be converted to pointers (depending on whether the capture set is empty) to functions but they do implement some of these traits.
So for example, the example from above can be expanded:
fn fun_test_impl(value: i32, f: impl Fn(i32) -> i32) -> i32 {
println!("{}", f(value));
value
}
fn fun_test_dyn(value: i32, f: &dyn Fn(i32) -> i32) -> i32 {
println!("{}", f(value));
value
}
fn fun_test_ptr(value: i32, f: fn(i32) -> i32) -> i32 {
println!("{}", f(value));
value
}
fn times2(value: i32) -> i32 {
2 * value
}
fn main() {
let y = 2;
//static dispatch
fun_test_impl(5, times2);
fun_test_impl(5, |x| 2*x);
fun_test_impl(5, |x| y*x);
//dynamic dispatch
fun_test_dyn(5, &times2);
fun_test_dyn(5, &|x| 2*x);
fun_test_dyn(5, &|x| y*x);
//C-like pointer to function
fun_test_ptr(5, times2);
fun_test_ptr(5, |x| 2*x); //ok: empty capture set
fun_test_ptr(5, |x| y*x); //error: expected fn pointer, found closure
}
Fn, FnMut and FnOnce, outlined in the other answer, are closure types. The types of functions that close over their scope.
Apart from passing closures Rust also supports passing simple (non-closure) functions, like this:
fn times2(value: i32) -> i32 {
2 * value
}
fn fun_test(value: i32, f: fn(i32) -> i32) -> i32 {
println!("{}", f (value));
value
}
fn main() {
fun_test (2, times2);
}
fn(i32) -> i32 here is a function pointer type.
If you don't need a full-fledged closure than working with function types is often simpler as it doesn't have to deal with those closure lifetime nicities.

borrowed value does not live long enough in this case ( Vec<&Fn(i32) -> i32> )

I am having this error, other times I had something similar and I have been able to solve, in different ways but now is not how to solve in this case:
borrowed value does not live long enough in
I moved the code that fails one more simple, but I can not find the error:
fn main(){
let mut v: Vec<&Fn(i32) -> i32> = Vec::new();
v.push(&ops_code1);
//v.push(&ops_code2);
//v.push(&ops_code3);
}
fn ops_code1(value: i32) -> i32 {
..//
error: borrowed value does not live long enough
v.push(&ops_code1);
play.rust
What you are doing here is creating a Vec of closures. In Rust static functions are treated slightly differently from closures, so when we create the reference a closure is actually created. If we do that after creating the Vec the resulting closure gets a shorter lifetime than the Vec, which is an error. We can instead use a let to create the closure before the Vec, giving a long enough lifetime, outliving the Vec:
fn main() {
let extended = &ops_code1;
let mut v: Vec<&Fn(i32) -> i32> = Vec::new();
// Note that placing it here does not work:
// let extended = &ops_code1;
v.push(extended);
//v.push(&ops_code2);
//v.push(&ops_code3);
}
fn ops_code1(value: i32) -> i32 {
println!("ops_code1 {}", value);
value
}
Rust Playground
However, if you only use static functions - and not closures - the following also works fine, and lets you avoid the extra let:
fn main() {
let mut v: Vec<fn(i32) -> i32> = Vec::new();
v.push(ops_code1);
v.push(ops_code2);
}
fn ops_code1(value: i32) -> i32 {
println!("ops_code1 {}", value);
value
}
fn ops_code2(value: i32) -> i32 {
println!("ops_code2 {}", value);
value
}
Rust Playground
A third option is to use boxed closures, which let's you use both closures and static functions without the extra lets, but with its own trade-offs:
fn main() {
let mut v: Vec<Box<Fn(i32) -> i32>> = Vec::new();
v.push(Box::new(ops_code1));
v.push(Box::new(ops_code2));
for f in v {
f(1);
}
}
fn ops_code1(value: i32) -> i32 {
println!("ops_code1 {}", value);
value
}
fn ops_code2(value: i32) -> i32 {
println!("ops_code2 {}", value);
value
}
Rust Playground

Resources