Mutating an upvar captured by value in a FnMut closure - closures

I am attempting to create a simple program, with a closure containing a collection that progressively empties itself:
fn main() {
let vector = vec![1, 2, 3];
let mut allow_once = move |i: &i32| -> bool {
if let Some(index) = vector.position_elem(i) {
vector.remove(index);
return true
}
false
};
for e in &[1, 2, 3, 1, 2, 3] {
let is_in = if allow_once(e) { "is" } else { "is not" };
println!("{} {} allowed", e, is_in);
}
}
It seems kosher (to me), but rustc complains (on nightly):
<anon>:6:13: 6:19 error: cannot borrow captured outer variable in an `FnMut` closure as mutable
<anon>:6 vector.remove(index);
^~~~~~
I expect that the issue might be one of desugaring. That is, while the implementation never violates the Aliasing XOR Mutation principle, maybe the desguaring is so that rustc does not realize it.
Thus:
Is this a temporary limitation/bug or is it intrinsic?
How can I create a closure with a mutable environment, as efficiently as possible?
Note: Capture by reference is not an option, I wish to be able to move the closure around.

The problem can be solved easily, in fact. Just add mut qualifier to vector:
fn main() {
let mut vector = vec![1, 2, 3];
let mut allow_once = move |i: &i32| -> bool {
if let Some(index) = vector.position_elem(i) {
vector.remove(index);
true
} else { false }
};
for e in &[1, 2, 3, 1, 2, 3] {
let is_in = if allow_once(e) { "is" } else { "is not" };
println!("{} {} allowed", e, is_in);
}
}
(working code here)
It's just the same mutability rules as always - in order to mutate something, it has to have mut somewhere, either in its variable declaration or in its type (&mut).

Related

With closures as parameter and return values, is Fn or FnMut more idiomatic?

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)

Borrowed RefCell does not last long enough when iterating over a list

I'm trying to implement a linked list to understand smart pointers in Rust. I defined a Node:
use std::{cell::RefCell, rc::Rc};
struct Node {
val: i32,
next: Option<Rc<RefCell<Node>>>,
}
and iterate like
fn iterate(node: Option<&Rc<RefCell<Node>>>) -> Vec<i32> {
let mut p = node;
let mut result = vec![];
loop {
if p.is_none() {
break;
}
result.push(p.as_ref().unwrap().borrow().val);
p = p.as_ref().unwrap().borrow().next.as_ref();
}
result
}
the compiler reports an error:
error[E0716]: temporary value dropped while borrowed
--> src/main.rs:27:13
|
27 | p = p.as_ref().unwrap().borrow().next.as_ref();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -
| | |
| | temporary value is freed at the end of this statement
| | ... and the borrow might be used here, when that temporary is dropped and runs the destructor for type `std::cell::Ref<'_, Node>`
| creates a temporary which is freed while still in use
| a temporary with access to the borrow is created here ...
|
= note: consider using a `let` binding to create a longer lived value
What happened? Can't we use a reference to iterate on a node defined this way?
Instead of assigning p the borrowed reference, you need to clone the Rc:
use std::cell::RefCell;
use std::rc::Rc;
struct Node {
val: i32,
next: Option<Rc<RefCell<Node>>>,
}
fn iterate(node: Option<Rc<RefCell<Node>>>) -> Vec<i32> {
let mut p = node;
let mut result = vec![];
loop {
let node = match p {
None => break,
Some(ref n) => Rc::clone(n), // Clone the Rc
};
result.push(node.as_ref().borrow().val); //works because val is Copy
p = match node.borrow().next {
None => None,
Some(ref next) => Some(Rc::clone(next)), //clone the Rc
};
}
result
}
fn main() {
let node = Some(Rc::new(RefCell::new(Node {
val: 0,
next: Some(Rc::new(RefCell::new(Node { val: 1, next: None }))),
})));
let result = iterate(node);
print!("{:?}", result)
}
This is necessary because you are trying to use a variable with a shorter lifespan in a context that requires a longer lifespan. The result of p.as_ref().unwrap().borrow() is dropped (i.e. freed, de-allocated) after the loop iteration, but you are trying to use its members in the next loop (this is called use after free and one of the design goals of Rust is to prevent that).
The issue is that borrows do not own the object. If you want to use the next as p in the next loop, then p will have to own the object. This can be achieved with Rc (i.e. 'reference counted') and allows for multiple owners in a single thread.
What if the definition of Node::next is Option<Box<RefCell<Node>>>, how to iterate over this list?
Yes, I'm also very confused with RefCell, without RefCell we can iterate over list using reference only, but will fail with RefCell. I even tried to add a vector of Ref to save the reference, but still can not success.
If you drop the RefCell you can iterate it like this:
struct Node {
val: i32,
next: Option<Box<Node>>,
}
fn iterate(node: Option<Box<Node>>) -> Vec<i32> {
let mut result = vec![];
let mut next = node.as_ref().map(|n| &**n);
while let Some(n) = next.take() {
result.push(n.val);
let x = n.next.as_ref().map(|n| &**n);
next = x;
}
result
}
fn main() {
let node = Some(Box::new(Node {
val: 0,
next: Some(Box::new(Node { val: 1, next: None })),
}));
let result = iterate(node);
print!("{:?}", result)
}
Maybe it's possible with a RefCell as well, but I was not able to work around the lifetime issues.
I bring a little different code from above answer, one match expression in the loop.
fn iterate(node: Option<Rc<RefCell<ListNode>>>) -> Vec<i32>{
let mut result = vec![];
let mut p = match node{
Some(x) => Rc::clone(&x),
None => return result,
};
loop {
result.push(p.as_ref().borrow().val); //works because val is Copy
let node = match &p.borrow().next{
Some(x) => Rc::clone(&x),
None => break,
};
p = node;
}
result
}

How can I specify a lifetime for closure arguments? [duplicate]

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>.

Conflicting lifetime requirements when storing closure capturing returned value

EDIT:
I'm trying to create a vector of closures inside a function, add a standard closure to the vector, and then return the vector from the function. I'm getting an error about conflicting lifetimes.
Code can be executed here.
fn vec_with_closure<'a, T>(f: Box<FnMut(T) + 'a>) -> Vec<Box<FnMut(T) + 'a>>
{
let mut v = Vec::<Box<FnMut(T)>>::new();
v.push(Box::new(|&mut: t: T| {
f(t);
}));
v
}
fn main() {
let v = vec_with_closure(Box::new(|t: usize| {
println!("{}", t);
}));
for c in v.iter_mut() {
c(10);
}
}
EDIT 2:
Using Rc<RefCell<...>> together with move || and the Fn() trait as opposed to the FnMut()m as suggested by Shepmaster, helped me produce a working version of the above code. Rust playpen version here.
Here's my understanding of the problem, slightly slimmed down:
fn filter<F>(&mut self, f: F) -> Keeper
where F: Fn() -> bool + 'static //'
{
let mut k = Keeper::new();
self.subscribe(|| {
if f() { k.publish() }
});
k
}
In this method, f is a value that has been passed in by-value, which means that filter owns it. Then, we create another closure that captures f by-reference. We are then trying to save that closure somewhere, so all the references in the closure need to outlive the lifetime of our struct (I picked 'static for convenience).
However, f only lives until the end of the method, so it definitely won't live long enough. We need to make the closure own f. It would be ideal if we could use the move keyword, but that causes the closure to also move in k, so we wouldn't be able to return it from the function.
Trying to solve that led to this version:
fn filter<F>(&mut self, f: F) -> Keeper
where F: Fn() -> bool + 'static //'
{
let mut k = Keeper::new();
let k2 = &mut k;
self.subscribe(move || {
if f() { k2.publish() }
});
k
}
which has a useful error message:
error: `k` does not live long enough
let k2 = &mut k;
^
note: reference must be valid for the static lifetime...
...but borrowed value is only valid for the block
Which leads to another problem: you are trying to keep a reference to k in the closure, but that reference will become invalid as soon as k is returned from the function. When items are moved by-value, their address will change, so references are no longer valid.
One potential solution is to use Rc and RefCell:
fn filter<F>(&mut self, f: F) -> Rc<RefCell<Keeper>>
where F: Fn() -> bool + 'static //'
{
let mut k = Rc::new(RefCell::new(Keeper::new()));
let k2 = k.clone();
self.subscribe(move || {
if f() { k2.borrow_mut().publish() }
});
k
}

Passing a closure to a recursive function

I'm working on a quad tree. Using a closure to determine when a region should be split seems like a good idea.
pub fn split_recursively(&mut self, f: |Rect| -> bool) {
...
self.children.as_mut().map(|children| {
children.nw.split_recursively(f);
children.ne.split_recursively(f);
children.sw.split_recursively(f);
children.se.split_recursively(f);
});
}
The above is what I have tried, but I get
error: cannot move out of captured outer variable
children.se.split_recursively(f);
For each of the four children.
I then tried wrapping the closure in a RefCell
fn split_recursively(&mut self, f: &RefCell<|Rect| -> bool>)
and calling it
let should_split = (*f.borrow_mut())(self.rect);
but Rust doesn't like that either:
error: closure invocation in a & reference
I know how to work around this by passing a function pointer and &mut to a rng (because splitting should in part depend on randomness), but a closure would be more elegant. Is there any way to get this to work with a closure? If not, would it be possible with unboxed closures?
Unboxed closures do work but they are currently feature-gated and add complexity.
#![feature(unboxed_closures)]
use std::ops::Fn;
fn main() {
let f = |&: x: uint| println!("Recurse {}!", x);
recursive(&f, 0);
}
fn recursive(f: &Fn<(uint,), ()>, depth: uint) {
if depth < 10 {
f.call((depth,)); // Cannot be invoked like f(depth) currently.
recursive(f, depth + 1);
} else {
()
}
}
(Rust-Playpen link)
Searching around, I found an easy solution. Just call the closure in a closure:
fn main() {
let f = |x: uint| println!("Recurse {}!", x);
recursive(f, 0);
}
fn recursive(f: |uint| -> (), depth: uint) {
if depth < 10 {
f(depth);
recursive(|x| f(x), depth + 1);
} else {
()
}
}
(Rust-Playpen link)
This has a performance impact compared to unboxed closures but it's definitely easier to read. Your choice.

Resources