This question already has an answer here:
How to pass anonymous functions as parameters in Rust?
(1 answer)
Closed 6 years ago.
I'm learning Rust right now, and it seems I can't specify a closure as a function parameter. Here's what I have:
fn foo(a: i32, f: |i32| -> i32) -> i32 {
f(a)
}
fn main() {
let bar = foo(5, |x| { x + 1 });
println!("{}", bar);
}
I get the following error:
foo.rs:1:19: 1:20 error: expected type, found `|`
foo.rs:1 fn foo(a: i32, f: |i32| -> i32) -> i32 {
Okay, so it didn't like the closure syntax. This is sort of annoying, because now I have to write this:
fn foo(a: i32, f: Box<Fn(i32) -> i32>) -> i32 {
f(a)
}
fn main() {
let bar = foo(5, Box::new(|x| { x + 1 }));
println!("{}", bar);
}
So what's going on? I've read in a few different places that the first example is valid, so was this "closure type parameter" syntax removed, or am I just doing something wrong?
If anyone is interested in this question today, here's the syntax with generics:
fn foo<F: Fn(i32) -> i32>(a: i32, f: F) -> i32 {
f(a)
}
fn main() {
let bar = foo(5, |x| { x + 1 });
println!("{}", bar);
}
Or, using trait objects:
fn foo(a: i32, f: Box<Fn(i32) -> i32>) -> i32 {
f(a)
}
fn main() {
let bar = foo(5, Box::new(|x| { x + 1 }));
println!("{}", bar);
}
You should prefer the former.
Rust has been developed in the open from the beginning and the language has evolved a lot since then. The Stack Overflow article you're linking to is almost 1 year old, which in pre-1.0 Rust time is as long as a lifetime... (pun intended)
The most straightforward answer would be: keep in mind that a lot of articles, blogs posts, SO answers... are not relevant anymore because the language changed. If you try a solution and it doesn't work, just find the newer syntax (as you did!) and move on.
For this specific case, this RFC documents the change from |...| -> ... to Fn/FnMut/FnOnce(...) -> ....
By the way, there is a plan for a community effort to find outdated articles and explicitly mark them as deprecated, in order for this particular problem to be avoided. I can't find the link to it, though.
Related
I am a beginner in Rust and am trying to create a Parser Combinator library in order to learn the ropes of the language. Very early on in this project I've gotten stuck. I want to have a Parser struct that holds the function used to parse data. Here is my attempt at implementing this.
struct Parser<I, O> {
parse: impl Fn(&Vec<I>) -> Option<(&Vec<I>, O)>
}
Unfortunately, as the compiler informs me, i can not use the "impl Trait" notation in this way. Another way I've tried is by defining a separate type variable for the type of the function itself, as below.
struct Parser<I, O, F>
where
F: impl Fn(&Vec<I>) -> Option<(&Vec<I>, O)>
{
parse: F
}
However, it seems redundant and unnecessary to have to provide the input, output, and function type, as the function type can be derived from the input and output. Also, the compiler gives me an error due to the fact that neither I or O are used.
I also considered Parser may have to be a trait rather than a struct. However I can't really wrap my head around what that would look like, and it seems like you would run into the same issue trying to define a struct that implemented the Parser trait.
Not a lot of context, but you I'll try doing it this way:
struct Parser<I, O> {
parse: Box<dyn Fn(&Vec<I>) -> Option<(&Vec<I>, O)>>,
}
fn main() {
let parser = Parser {
parse: Box::new(|x| {
Some((x, x.iter().sum::<i32>()))
})
};
let v = vec![1, 2, 3, 4];
let result = (parser.parse)(&v).unwrap();
println!("{:?}", result);
}
For some more suggestion I would look here: How do I store a closure in a struct in Rust?
I think all you need is std::marker::PhantomData to silence the error about unused generics. You can also make the code a bit more DRY with some type aliases. (I've replaced &Vec<I> with &[I] as the latter is a strict superset of the former.)
use std::marker::PhantomData;
type Input<'a,I> = &'a [I];
type Output<'a,I,O> = Option<(&'a [I], O)>;
struct Parser<I, O, F>
where
F: Fn(Input<'_,I>) -> Output<'_, I, O>,
{
parse: F,
_phantom: PhantomData<(I, O)>,
}
impl<I, O, F> Parser<I, O, F>
where
F: Fn(Input<'_, I>) -> Output<'_, I, O>,
{
fn new(parse: F) -> Self {
Self {
parse,
_phantom: PhantomData,
}
}
fn parse_it<'a>(&'a self, input: Input<'a, I>) -> Output<'a, I, O> {
(self.parse)(input)
}
}
fn main() {
let parser = Parser::new(|v: &[i32]| Some((v, v.iter().fold(0, |acc, x| acc + x))));
println!("{:?}", parser.parse_it(&[1, 2, 3]));
// ^ Some(([1, 2, 3], 6))
}
Continuing from How do I write combinators for my own parsers in Rust?, I stumbled into this question concerning bounds of functions that consume and/or yield functions/closures.
From these slides, I learned that to be convenient for consumers, you should try to take functions as FnOnce and return as Fn where possible. This gives the caller most freedom what to pass and what to do with the returned function.
In my example, FnOnce is not possible because I need to call that function multiple times. While trying to make it compile I arrived at two possibilities:
pub enum Parsed<'a, T> {
Some(T, &'a str),
None(&'a str),
}
impl<'a, T> Parsed<'a, T> {
pub fn unwrap(self) -> (T, &'a str) {
match self {
Parsed::Some(head, tail) => (head, &tail),
_ => panic!("Called unwrap on nothing."),
}
}
pub fn is_none(&self) -> bool {
match self {
Parsed::None(_) => true,
_ => false,
}
}
}
pub fn achar(character: char) -> impl Fn(&str) -> Parsed<char> {
move |input|
match input.chars().next() {
Some(c) if c == character => Parsed::Some(c, &input[1..]),
_ => Parsed::None(input),
}
}
pub fn some_v1<T>(parser: impl Fn(&str) -> Parsed<T>) -> impl Fn(&str) -> Parsed<Vec<T>> {
move |input| {
let mut re = Vec::new();
let mut pos = input;
loop {
match parser(pos) {
Parsed::Some(head, tail) => {
re.push(head);
pos = tail;
}
Parsed::None(_) => break,
}
}
Parsed::Some(re, pos)
}
}
pub fn some_v2<T>(mut parser: impl FnMut(&str) -> Parsed<T>) -> impl FnMut(&str) -> Parsed<Vec<T>> {
move |input| {
let mut re = Vec::new();
let mut pos = input;
loop {
match parser(pos) {
Parsed::Some(head, tail) => {
re.push(head);
pos = tail;
}
Parsed::None(_) => break,
}
}
Parsed::Some(re, pos)
}
}
#[test]
fn try_it() {
assert_eq!(some_v1(achar('#'))("##comment").unwrap(), (vec!['#', '#'], "comment"));
assert_eq!(some_v2(achar('#'))("##comment").unwrap(), (vec!['#', '#'], "comment"));
}
playground
Now I don't know which version is to be preferred. Version 1 takes Fn which is less general, but version 2 needs its parameter mutable.
Which one is more idiomatic/should be used and what is the rationale behind?
Update: Thanks jplatte for the suggestion on version one. I updated the code here, that case I find even more interesting.
Comparing some_v1 and some_v2 as you wrote them I would say version 2 should definitely be preferred because it is more general. I can't think of a good example for a parsing closure that would implement FnMut but not Fn, but there's really no disadvantage to parser being mut - as noted in the first comment on your question this doesn't constrain the caller in any way.
However, there is a way in which you can make version 1 more general (not strictly more general, just partially) than version 2, and that is by returning impl Fn(&str) -> … instead of impl FnMut(&str) -> …. By doing that, you get two functions that each are less constrained than the other in some way, so it might even make sense to keep both:
Version 1 with the return type change would be more restrictive in its argument (the callable can't mutate its associated data) but less restrictive in its return type (you guarantee that the returned callable doesn't mutate its associated data)
Version 2 would be less restrictive in its argument (the callable is allowed to mutate its associated data) but more restrictive in its return type (the returned callable might mutate its associated data)
I have a closure that captures and modifies its environment. I want to pass this closure to a function that accepts closures:
fn main() {
let mut integer = 5;
let mut closure_variable = || -> i32 {
integer += 1;
integer
};
execute_closure(&mut closure_variable);
}
fn execute_closure(closure_argument: &mut Fn() -> i32) {
let result = closure_argument();
println!("Result of closure: {}", result);
}
Because the closure modifies its environment, this fails:
error[E0525]: expected a closure that implements the `Fn` trait, but this closure only implements `FnMut`
--> src/main.rs:3:32
|
3 | let mut closure_variable = || -> i32 {
| ________________________________^
4 | | integer += 1;
5 | | integer
6 | | };
| |_____^
7 | execute_closure(&mut closure_variable);
| --------------------- the requirement to implement `Fn` derives from here
|
note: closure is `FnMut` because it mutates the variable `integer` here
--> src/main.rs:4:9
|
4 | integer += 1;
| ^^^^^^^
As I understand from When does a closure implement Fn, FnMut and FnOnce?, this means that my closure actually is expanded to a struct that implements the trait FnMut. This trait is mutable, meaning calling the function changes the (implicit) object. I think this correct, because the variable integer should be modified after calling execute_closure().
How do I convince the compiler this is okay and that I actually want to call a FnMut function? Or is there something fundamentally wrong with how I use Rust in this example?
If you can change the function that accepts the closure...
Accept a FnMut instead of a Fn:
fn main() {
let mut integer = 5;
execute_closure(|| {
integer += 1;
integer
});
}
fn execute_closure<F>(mut closure_argument: F)
where
F: FnMut() -> i32,
{
let result = closure_argument();
println!("Result of closure: {}", result);
}
If you can not change the function that accepts the closure...
Use interior mutability provided by types like Cell or RefCell:
use std::cell::Cell;
fn main() {
let integer = Cell::new(5);
execute_closure(|| {
integer.set(integer.get() + 1);
integer.get()
});
}
fn execute_closure<F>(closure_argument: F)
where
F: Fn() -> i32,
{
let result = closure_argument();
println!("Result of closure: {}", result);
}
Or is there something fundamentally wrong with how I use Rust in this example?
Perhaps. An argument of type &mut Fn() -> i32 cannot mutate the variables it has closed over, so the error message makes sense to me.
It's kind of similar to the type &mut &u8 — you could alter the outer reference to point to another immutable reference, but you cannot "ignore" the inner immutability and change the numeric value.
Aside:
The original code uses dynamic dispatch because there is a trait object that provides indirection. In many cases you'd see this version that I posted above, which uses static dispatch and can be monomorphized. I've also inlined the closure as that's the normal syntax.
Here's the original version with just enough changes to work:
fn main() {
let mut integer = 5;
let mut closure_variable = || -> i32 {
integer += 1;
integer
};
execute_closure(&mut closure_variable);
}
fn execute_closure(closure_argument: &mut FnMut() -> i32) {
let result = closure_argument();
println!("Result of closure: {}", result);
}
This question already has answers here:
How to declare a higher-ranked lifetime for a closure argument?
(3 answers)
Returning a higher-kinded closure that captures a reference
(1 answer)
Why does this closure require inlining or `dyn`? What does `dyn` do here?
(1 answer)
Expected bound lifetime parameter, found concrete lifetime [E0271]
(1 answer)
Closed last year.
Playpen link: http://is.gd/EpX6lM
I have a closure that takes a slice and returns a subslice of it. Compiling the following code on rust-1.0.0-beta-2 fails:
trait OptionalFirst {
fn optional_first<'a>(&self, x: &'a [usize]) -> &'a [usize];
}
impl<F> OptionalFirst for F where F: Fn(&[usize]) -> &[usize] {
fn optional_first<'a>(&self, x: &'a [usize]) -> &'a [usize] {
(*self)(x)
}
}
fn main() {
let bc: Box<OptionalFirst> = Box::new(
|x: &[usize]| -> &[usize] {
if x.len() != 0 {
&x[..1]
}
else {
&x[..0]
}
}) as Box<OptionalFirst>;
let a: [usize; 3] = [1, 2, 3];
let b: &[usize] = bc.optional_first(&a);
println!("{:?}", b);
}
I know how to define a lifetime in a closure's type (using for <'a>), but I don't know how to specify it in the closure's implementation.
Your implementation impl<F> OptionalFirst for F where F: Fn(&[usize]) -> &[usize] is expecting a bound lifetime parameter, for the constraint F: Fn(&[usize]) -> &[usize] is, expanded to full form: F: for<'a> Fn(&'a [usize]) -> &'a [usize].
That is, at the time you call the function, it will determine what values to select for the lifetime (they are generics).
A closure, however, cannot have any bound lifetime parameters; they are by stuck using concrete lifetime parameters. They lack the facility to wire output lifetimes to input lifetimes generically as you want: they are by very design concrete and not generic. I haven’t thought about this in great depth, but it might be possible to counteract this for generic lifetime parameters; it is not, however, something that is implemented as far as I am aware.
If you want something like this, try using a function rather than a closure. When you’re not using any of the environment there’s no benefit to using closures beyond the typically lower verbosity.
Here’s what you end up with:
fn bc(x: &[usize]) -> &[usize] {
if x.len() != 0 {
&x[..1]
} else {
&x[..0]
}
}
Playpen
You can create a closure with bound lifetime parameters, you just have to get the compiler to infer that type correctly. It can be done like this:
fn main() {
let bc: Box<Fn(&[usize]) -> &[usize]> = Box::new(
|x| {
if x.len() != 0 {
&x[..1]
}
else {
&x[..0]
}
});
let a: [usize; 3] = [1, 2, 3];
let b: &[usize] = bc(&a);
println!("{:?}", b);
}
However, what I don't know is how to cast it further into Box<OptionalFirst>.
A FnMut closure cannot be cloned, for obvious reasons, but a Fn closure has an immutable scope; is there some way to create a "duplicate" of a Fn closure?
Trying to clone it results in:
error[E0599]: no method named `clone` found for type `std::boxed::Box<std::ops::Fn(i8, i8) -> i8 + std::marker::Send + 'static>` in the current scope
--> src/main.rs:22:25
|
22 | fp: self.fp.clone(),
| ^^^^^
|
= note: self.fp is a function, perhaps you wish to call it
= note: the method `clone` exists but the following trait bounds were not satisfied:
`std::boxed::Box<std::ops::Fn(i8, i8) -> i8 + std::marker::Send> : std::clone::Clone`
Is it safe to somehow pass a raw pointer to a Fn around, like:
let func_pnt = &mut Box<Fn<...> + Send> as *mut Box<Fn<...>>
Technically, the above works, but it seems quite weird.
Here's an example of what I'm trying to do:
use std::thread;
struct WithCall {
fp: Box<Fn(i8, i8) -> i8 + Send>,
}
impl WithCall {
pub fn new(fp: Box<Fn(i8, i8) -> i8 + Send>) -> WithCall {
WithCall { fp: fp }
}
pub fn run(&self, a: i8, b: i8) -> i8 {
(self.fp)(a, b)
}
}
impl Clone for WithCall {
fn clone(&self) -> WithCall {
WithCall {
fp: self.fp.clone(),
}
}
}
fn main() {
let adder = WithCall::new(Box::new(|a, b| a + b));
println!("{}", adder.run(1, 2));
let add_a = adder.clone();
let add_b = adder.clone();
let a = thread::spawn(move || {
println!("In remote thread: {}", add_a.run(10, 10));
});
let b = thread::spawn(move || {
println!("In remote thread: {}", add_b.run(10, 10));
});
a.join().expect("Thread A panicked");
b.join().expect("Thread B panicked");
}
playground
I have a struct with a boxed closure in it, and I need to pass that struct to a number of threads. I can't, but I also can't clone it, because you can't clone a Box<Fn<>> and you can't clone a &Fn<...>.
What you are trying to do is call a closure from multiple threads. That is, share the closure across multiple threads. As soon as the phrase "share across multiple threads" crosses my mind, my first thought is to reach for Arc (at least until RFC 458 is implemented in some form, when & will become usable across threads).
This allows for safe shared memory (it implements Clone without requiring its internal type to be Clone, since Clone just creates a new pointer to the same memory), and so you can have a single Fn object that gets used in multiple threads, no need to duplicate it.
In summary, put your WithCall in an Arc and clone that.
use std::sync::Arc;
use std::thread;
type Fp = Box<Fn(i8, i8) -> i8 + Send + Sync>;
struct WithCall {
fp: Fp,
}
impl WithCall {
pub fn new(fp: Fp) -> WithCall {
WithCall { fp }
}
pub fn run(&self, a: i8, b: i8) -> i8 {
(self.fp)(a, b)
}
}
fn main() {
let adder = WithCall::new(Box::new(|a, b| a + b));
println!("{}", adder.run(1, 2));
let add_a = Arc::new(adder);
let add_b = add_a.clone();
let a = thread::spawn(move || {
println!("In remote thread: {}", add_a.run(10, 10));
});
let b = thread::spawn(move || {
println!("In remote thread: {}", add_b.run(10, 10));
});
a.join().expect("thread a panicked");
b.join().expect("thread b panicked");
}
playground
Old answer (this is still relevant): It is quite unusual to have a &mut Fn trait object, since Fn::call takes &self. The mut is not necessary, and I think it adds literally zero extra functionality. Having a &mut Box<Fn()> does add some functionality, but it is also unusual.
If you change to a & pointer instead of an &mut things will work more naturally (with both &Fn and &Box<Fn>). Without seeing the actual code you're using, it's extremely hard to tell exactly what you're doing, but
fn call_it(f: &Fn()) {
(*f)();
(*f)();
}
fn use_closure(f: &Fn()) {
call_it(f);
call_it(f);
}
fn main() {
let x = 1i32;
use_closure(&|| println!("x is {}", x));
}
(This is partly due to &T being Copy and also partly due to reborrowing; it works with &mut as well.)
Alternatively, you can close-over the closure, which likely works in more situations:
fn foo(f: &Fn()) {
something_else(|| f())
}
A FnMut closure cannot be cloned, for obvious reasons.
There's no inherent reason a FnMut can't be cloned, it's just a struct with some fields (and a method that takes &mut self, rather than &self or self as for Fn and FnOnce respectively). If you create a struct and implement FnMut manually, you can still implement Clone for it.
Or is it safe to somehow pass a raw pointer to a Fn around, like:
let func_pnt = &mut Box<Fn<...> + Send> as *mut Box<Fn<...>>
Technically the above works, but it seems quite weird.
Technically it works if you're careful to ensure the aliasing and lifetime requirements of Rust are satisfied... but by opting in to unsafe pointers you're putting that burden on yourself, not letting the compiler help you. It is relatively rare that the correct response to a compiler error is to use unsafe code, rather than delving in to the error and tweaking the code to make it make more sense (to the compiler, which often results in it making more sense to humans).
Rust 1.26
Closures implement both Copy and Clone if all of the captured variables do. You can rewrite your code to use generics instead of a boxed trait object to be able to clone it:
use std::thread;
#[derive(Clone)]
struct WithCall<F> {
fp: F,
}
impl<F> WithCall<F>
where
F: Fn(i8, i8) -> i8,
{
pub fn new(fp: F) -> Self {
WithCall { fp }
}
pub fn run(&self, a: i8, b: i8) -> i8 {
(self.fp)(a, b)
}
}
fn main() {
let adder = WithCall::new(|a, b| a + b);
println!("{}", adder.run(1, 2));
let add_a = adder.clone();
let add_b = adder;
let a = thread::spawn(move || {
println!("In remote thread: {}", add_a.run(10, 10));
});
let b = thread::spawn(move || {
println!("In remote thread: {}", add_b.run(10, 10));
});
a.join().expect("Thread A panicked");
b.join().expect("Thread B panicked");
}
Before Rust 1.26
Remember that closures capture their environment, so they have a lifetime of their own, based on the environment. However, you can take references to the Fn* and pass those around further, or store them in a struct:
fn do_more<F>(f: &F) -> u8
where
F: Fn(u8) -> u8,
{
f(0)
}
fn do_things<F>(f: F) -> u8
where
F: Fn(u8) -> u8,
{
// We can pass the reference to our closure around,
// effectively allowing us to use it multiple times.
f(do_more(&f))
}
fn main() {
let val = 2;
// The closure captures `val`, so it cannot live beyond that.
println!("{:?}", do_things(|x| (x + 1) * val));
}
I would say that it is not universally safe to convert the Fn* to a raw pointer and pass it around, due to the lifetime concerns.
Here is the working code in 1.22.1
The intent is to make this work.
let x = |x| { println!("----{}",x)};
let mut y = Box::new(x);
y.clone();
The original code as suggested at the top was used.
I started with cloning a Fn closure.
type Fp = Box<Fn(i8, i8) -> i8 + Send + Sync>;
Ended up adding Arc around Fp in the struct WithCall
Play rust : working code
Gist : working code in 1.22.1