How to call a recursive closure in a new thread? - rust

tool is a grab-bag of useful functions for functional programming includes making recursive closure, for example:
extern crate tool;
use tool::prelude::*;
fn main() {
let fib = fix(move |f, x| {
if x == 0 || x == 1 {
x
} else {
// `f` is `fib`
f(x - 1) + f(x - 2)
}
});
println!("{}", fib(10)); // print 55
}
Things I want to implement is here : playground
Here's the overview: I'm defining a function A which take a function B as parameter, again the function B take function C as parameter. I need to call the function C in a new thread, In this case using &dyn keyword for the inner function gives me an error:
fn a(b: impl Fn(&dyn Fn() -> ()) -> ()) -> () {
// ...
}
error[E0277]: `dyn std::ops::Fn() ->()` cannot be shared between threads safely
I try the syntax like below, but this gives me an another error:
fn a(b: impl Fn(impl Fn() -> ()) -> ()) -> () {
// ...
}
error[E0666]: nested `impl Trait` is not allowed
--> src/main.rs:2:21
|
2 | fn a(b: impl Fn(impl Fn() -> ()) -> ()) -> () {
| --------^^^^^^^^^^^^^^^-------
| | |
| | nested `impl Trait` here
| outer `impl Trait`

Related

Is there no way to (one way or another) create an owned version of a (Box of) closure in rust?

I want to write a FuncWrapper struct with a new function that takes a (Boxed) closure as parameter, and returns a decorated closure that just adds some boilerplate to the incoming one. But I also want the returned value to be "owned", to allow for the following (e.g.):
fn main() {
let a: FuncWrapper<u32>;
{
let foo = |x: u32| {print!("{}", x)};
let b = &Box::new(foo);
a = FuncWrapper::new(b);
}
let _c = (a.func)(42);
}
That is, I want for the return value of new to be an "owned" value.
Now I recently learned that all closures in Rust (being Trais) must have a lifetime associated with them (and it will default to 'static if not specified.) But I suppose its seems that any lifetime for the closure in the FuncWrapper of the return value of new will be wrong.
I don't want the lifetime to be that of the incoming reference, because this will be too short. E.g. the following will not work because it the lifetime of the return value is that of the parameter f_box_ref which does not live long enough in the case I provide above
struct FuncWrapper<'b, DomainType> {
func: Box<dyn Fn(DomainType) + 'b>
}
impl<'b, DomainType> FuncWrapper<'b, DomainType> {
fn new<F: Fn(DomainType) + 'static>(f_box_ref: &'b Box<F>) -> FuncWrapper<'b, DomainType> {
let new_f = move |a: DomainType| {
// ..add some boilerplate then
(**f_box_ref)(a)
};
let b = Box::new(new_f);
FuncWrapper {func: b}
}
}
results in
error[E0716]: temporary value dropped while borrowed
--> src/main.rs:22:18
|
22 | let b = &Box::new(foo);
| ^^^^^^^^^^^^^ creates a temporary which is freed while still in use
23 | a = FuncWrapper::new(b);
24 | }
| - temporary value is freed at the end of this statement
...
27 | }
| - borrow might be used here, when `a` is dropped and runs the destructor for type `FuncWrapper<'_, u32>`
|
= note: consider using a `let` binding to create a longer lived value
Changing the lifetime of the return parameter to 'static also seems wrong, since my goal is to create a new closure inside the new function`, (so how could it be static?) but regardless this:
struct FuncWrapper<DomainType> {
func: Box<dyn Fn(DomainType) + 'static>
}
impl<DomainType> FuncWrapper<DomainType> {
fn new<'b, F: Fn(DomainType) + 'static>(f_box_ref: &'b Box<F>) -> FuncWrapper<DomainType> {
let new_f = move |a: DomainType| {
// ..add some boilerplate then
(**f_box_ref)(a)
};
let b = Box::new(new_f);
FuncWrapper {func: b}
}
}
errors with
error[E0759]: `f_box_ref` has lifetime `'b` but it needs to satisfy a `'static` lifetime requirement
--> src/main.rs:7:21
|
6 | fn new<'b, F: Fn(DomainType) + 'static>(f_box_ref: &'b Box<F>) -> FuncWrapper<DomainType> {
| ---------- this data with lifetime `'b`...
7 | let new_f = move |a: DomainType| {
| _____________________^
8 | | // ..add some boilerplate then
9 | | (**f_box_ref)(a)
10 | | };
| |_________^ ...is used here...
11 | let b = Box::new(new_f);
12 | FuncWrapper {func: b}
| - ...and is required to live as long as `'static` here
The error surprised me since I thought the job of move was to capture by value. At first I thought that I need to dereference the f_box_ref first? But that
impl<DomainType> FuncWrapper<DomainType> {
fn new<'b, F: Fn(DomainType) + 'static>(f_box_ref: &'b Box<F>) -> FuncWrapper<DomainType> {
let f_box: Box<F> = *f_box_ref;
let new_f = move |a: DomainType| {
// ..add some boilerplate then
(*f_box)(a)
};
let b = Box::new(new_f);
FuncWrapper {func: b}
}
}
results in
error[E0507]: cannot move out of `*f_box_ref` which is behind a shared reference
--> src/main.rs:7:30
|
7 | let f_box: Box<F> = *f_box_ref;
| ^^^^^^^^^^
| |
| move occurs because `*f_box_ref` has type `Box<F>`, which does not implement the `Copy` trait
| help: consider borrowing here: `&*f_box_ref`
Alas, following the hint to "help: consider borrowing here: &*f_box_ref" doesn't help either
impl<DomainType> FuncWrapper<DomainType> {
fn new<'b, F: Fn(DomainType) + 'static>(f_box_ref: &'b Box<F>) -> FuncWrapper<DomainType> {
let f_box: &Box<F> = &*f_box_ref;
let new_f = move |a: DomainType| {
// ..add some boilerplate then
(*f_box)(a)
};
let b = Box::new(new_f);
FuncWrapper {func: b}
}
}
errors with
error[E0759]: `f_box_ref` has lifetime `'b` but it needs to satisfy a `'static` lifetime requirement
--> src/main.rs:7:31
|
6 | fn new<'b, F: Fn(DomainType) + 'static>(f_box_ref: &'b Box<F>) -> FuncWrapper<DomainType> {
| ---------- this data with lifetime `'b`...
7 | let f_box: &Box<F> = &*f_box_ref;
| ^^^^^^^^^^^ ...is used here...
...
13 | FuncWrapper {func: b}
| - ...and is required to live as long as `'static` here
so obviously we're still not returning anything like a new owned closure, and any choice for the lifetime of the returned closure seems arbitrary and wrong.
What I'm trying to do here seems like it should be common. What am I missing?
It's fairly straight forward, to get an owned type from a reference you have 3 options that come to mind immediately:
Copy, Clone or ToOwned.
ToOwned is a little more advanced since it can change the type as well and since Copy requires Cloned I'll focus on the later.
To get an owned Fn from a &Box<Fn> you can just call clone():
impl<DomainType> FuncWrapper<DomainType> {
fn new<F: Fn(DomainType) + Clone + 'static>(f_box_ref: &Box<F>) -> FuncWrapper<DomainType> {
let f_box = f_box_ref.clone();
let new_f = move |a: DomainType| {
// ..add some boilerplate then
(f_box)(a)
};
let b = Box::new(new_f);
FuncWrapper { func: b }
}
}
Since it is not FnMut, just Fn maybe you can use an Rc instead of Box? You can always clone an Rc
use std::rc::Rc;
impl<DomainType> FuncWrapper<DomainType> {
fn new<F: Fn(DomainType) + 'static>(f_rc: Rc<F>) -> FuncWrapper<DomainType> {
let new_f = move |a: DomainType| {
// ..add some boilerplate then
(f_rc)(a)
};
let b = Box::new(new_f);
FuncWrapper { func: b }
}
}

Pass variable into a scope in rust

I have a problem trying to implement a callback to filter method in Rust. I have this function:
fn filter_by_mod(num: i32) -> fn(x: &i32) -> bool {
let func = |x: &i32| {
x.to_owned() % num == 0
};
return func;
}
I am trying to filter by mod and I would like to pass the number by paramenter and use in the func clousure, but when I try to compile I have the following error:
fn filter_by_mod(num: i32) -> fn(x: &i32) -> bool {
| ------------------- expected `for<'r> fn(&'r i32) -> bool` because of return type
9 | let func = |x: &i32| {
| ________________-
10 | | x.to_owned() % num == 0
11 | | };
| |_____- the found closure
12 | return func;
| ^^^^ expected fn pointer, found closure
|
= note: expected fn pointer `for<'r> fn(&'r i32) -> bool`
found closure `[closure#.\main.rs:9:16: 11:6]`
note: closures can only be coerced to `fn` types if they do not capture any variables
--> .\main.rs:10:24
|
10 | x.to_owned() % num == 0
| ^^^ `num` captured here
error: aborting due to previous error
How I can pass the number to func scope? I hope that you can understandme, because my english is not good. Thanks.
There are 2 problems why the example does not compile:
You are returning fn type. In rust it is a function pointer, but a closure is not a function, so you need to return an implementation of Fn trait.
But default closure borrows the context parameters, so you need to move it:
fn filter_by_mod(num: i32) -> impl Fn(&i32) -> bool {
let func = move |x: &i32| {
x.to_owned() % num == 0
};
return func;
}
Two things happening here:
You need to move num into the new function
Your function signature is wrong, you cannot return a function pointer, you need to use impl + function trait signature needed.
With minor stylish adjustments too:
fn filter_by_mod(num: i32) -> impl Fn(&i32) -> bool {
move |x: &i32| {
x.to_owned() % num == 0
}
}
Playground

Cannot set default function closure [duplicate]

This question already has answers here:
Dynamically select a function to call without intermediate variables
(2 answers)
Closed 10 months ago.
I am trying to create a method that takes an Option<impl Fn() -> ()> as a parameter, and, if this parameter is Some(func), stores func as a closure, but, if it is None, stores some default function as the closure. Specifically, my code is as follows:
fn foo()
{
println!("HI");
}
fn bar(baz: Option<impl Fn () -> ()>)
{
let func = match baz {
Some(func) => func,
//None => foo,
None => unimplemented!()
};
func();
}
pub fn main() {
bar(Some(foo));
}
As-is, the code compiles, which indicates to me that foo is indeed something that should work with impl Fn () -> (). However, if I swap out the None arm of my match with the commented out None arm to set foo as my "default implentation", I get the following error:
error[E0308]: `match` arms have incompatible types
--> <source>:10:17
|
6 | fn bar(baz: Option<impl Fn () -> ()>)
| ---------------- this type parameter
7 | {
8 | let func = match baz {
| ________________-
9 | | Some(func) => func,
| | ---- this is found to be of type `impl Fn() -> ()`
10 | | None => foo,
| | ^^^ expected type parameter `impl Fn() -> ()`, found fn item
11 | | //None => unimplemented!()
12 | | };
| |_____- `match` arms have incompatible types
|
= note: expected type `impl Fn() -> ()`
found fn item `fn() {foo}`
error: aborting due to previous error
As far as I can tell from the error, it is saying that foo does not qualify as impl Fn() -> () within the function (though it did when passed in as a parameter). What am I missing here that causes this, and is there a way to accomplish what I want here (take an optional closure as a parameter, and use a default function as a closure if none provided)?
All the arms of a match statement must resolve to the exact same type.
With that in mind, let's replace impl Fn() -> () (which is also the same as impl Fn() BTW) with the generics that it represents:
fn bar<T>(baz: Option<T>) where T: Fn() {
// ...
}
impl Trait (in a function parameter) is syntactic sugar for regular generics, so this is "what the compiler sees".
Then let's look at the match:
fn bar<T>(baz: Option<T>) where T: Fn() {
let f = match baz {
Some(f) => f,
None => foo,
};
}
This can't work, because the type of foo is a special thing called a "function item" (essentially a unique type), but the type of f is a generic parameter T: it could be any type imaginable (as long as it implements Fn()). Clearly, these might be different, so Rust rejects the match statement as "having incompatible types".
What you're looking for is a trait object (though this comes at the cost of a heap allocation and vtable dispatch):
fn bar(baz: Option<impl Fn()>) {
let f: Box<dyn Fn()> = match baz {
Some(f) => Box::new(f),
None => Box::new(foo),
};
f();
}
Or, you can call the function immediately without storing in a variable:
fn bar(baz: Option<impl Fn()>) {
match baz {
Some(f) => f(),
None => foo(),
};
}
This is likely to be faster than the dyn Fn() approach above, though of course, if you are later storing it in a struct, this will not work.

How to implement a trait for a generic type of function pointer, no matter whose arguments types are references or not

I want: for a trait, e.g. Foo, any fn(T1,T2)->() should implement it, and I don't care whether T1 or T2 is a reference or not.
trait Foo {
fn hello_world(&self) -> String {
"hello world".into()
}
}
impl<T1, T2> Foo for fn(T1, T2) -> () {}
fn a_dummy_sample_function(_: i32, _:i32) {}
fn main() {
let fn_ptr : fn(i32, i32)->() = a_dummy_sample_function;
(fn_ptr).hello_world();
}
So far, it works well.
If I change the type of first argument to &i32,
trait Foo {
fn hello_world(&self) -> String {
"hello world".into()
}
}
impl<T1, T2> Foo for fn(T1, T2) -> () {}
fn foo_imp(_: &i32, _:i32) {}
fn main() {
let fn_ptr : fn(&i32, i32)->() = foo_imp;
fn_ptr.hello_world();
}
Then, I've got the following compilation errors.
--> src/main.rs:12:12
|
12 | fn_ptr.hello_world();
| ^^^^^^^^^^^ method not found in `for<'r> fn(&'r i32, i32)`
|
= note: `fn_ptr` is a function, perhaps you wish to call it
= help: items from traits can only be used if the trait is implemented and in scope
note: `Foo` defines an item `hello_world`, perhaps you need to implement it
I can fix the compilation error as below
impl<T1, T2> Foo for for<'a> fn(&'a T1, T2) -> () {}
But it is not what I want, I want any function pointer with any types of two arguments whether it is a reference or not.

How to alias an impl trait?

I have many functions of the following type signature:
fn f() -> impl Fn(u32) -> u32 {
|x: u32| x
}
How can I give a name to Fn(u32) -> u32 so that I don't have to repeat it? Although I can do type X = Fn(u32) -> u32;, Rust will not let me use this because it is a type and not a trait. Must I wait for trait_alias or can I do something else?
You're exactly right. impl X requires X to be a trait, and it's impossible to have proper trait aliases until trait aliases land. When that happens you'll be able to do this:
#![feature(trait_alias)]
trait X = Fn(u32) -> u32;
fn f() -> impl X {
|x: u32| x
}
(playground)
Alternatively, when Permit impl Trait in type aliases lands, you'll be able to make impl trait a type alias. This is slightly different though. When we alias with type X = impl Trait, the compiler will ensure that every usage of X is actually the same concrete type. That would mean that, in your case, you wouldn't be able to use this with multiple different closures, since every closure has its own unique type.
#![feature(type_alias_impl_trait)]
type X = impl Fn(u32) -> u32;
fn f() -> X {
|x: u32| x
}
(playground)
However, this won't compile.
#![feature(type_alias_impl_trait)]
type X = impl Fn(u32) -> u32;
fn f() -> X {
|x: u32| x
}
// Even a closure with exactly the same form has a different type.
fn g() -> X {
|x: u32| x
}
The error is
error: concrete type differs from previous defining opaque type use
--> src/lib.rs:10:1
|
10 | / fn g() -> X {
11 | | |x: u32| x
12 | | }
| |_^ expected `[closure#src/lib.rs:7:5: 7:15]`, got `[closure#src/lib.rs:11:5: 11:15]`
|
note: previous use here
--> src/lib.rs:6:1
|
6 | / fn f() -> X {
7 | | |x: u32| x
8 | | }
| |_^
(playground)
This is in contrast to trait aliases, which would allow a different concrete type to be used with every function returning impl TraitAlias. See the RFCs that introduced this syntax and existential types in general for more.
Until one of those two features lands, you can get similar behavior to the trait alias with what is essentially a hack. The idea is to make a new trait which is essentially equivalent to the original trait, but has a shorter name.
// This trait is local to this crate,
// so we can implement it on any type we want.
trait ShortName: Fn(u32) -> u32 {}
// So let's go ahead and implement `ShortName`
// on any type that implements `Fn(u32) -> u32`.
impl<T: Fn(u32) -> u32> ShortName for T {}
// We can use `ShortName` to alias `Fn(u32) -> u32`.
fn f() -> impl ShortName {
|x: u32| x
}
// Moreover, the result of that can be used in places
// that expect `Fn(u32) -> u32`.
fn g<T: Fn(u32) -> u32>(x: &T) -> u32 {
x(6_u32)
}
fn main() {
// We only know that `x` implements `ShortName`,
let x = f();
// But we can still use `x` in `g`,
// which expects an `Fn(u32) -> u32` argument
let _ = g(&x);
}
(playground)

Resources