I am implementing the recursion feature for nameable closures. In development I passed the following test:
#[test]
fn test_fac() {
let fac:ClosureRec<(),(i32,),i32> =
closure_rec!(me.state=() => ref |i|
if i==0 {1} else {me.stable_call((i-1,)) * i}
);
assert_eq!(fac.stable_call((10,)),3628800);
}
#[test]
fn test_fib() {
let fib:ClosureRec<(i32,i32),(i32,),i32> =
closure_rec!(me.state=(1,1) => ref |i| {
let (i0,i1) = me.state;
match i {
0 => i0,
1 => i1,
n => me.call_with_state((i1,i0+i1), (i-1,))
}
});
assert_eq!(fib.stable_call((10,)),89);
assert_eq!(fib.state, (1,1));
}
Things to note:
-
me is a variable name only, not a special word. It can be any legal identifiers.
-
state is a fixed field name, and is public to allow access from the body.
- The
ref keyword in front of the closure parameter block indicate that the self referencing variable me in the body is a reference to the closure itself. Without this the value will be moved to the body. Alternatively you can use ref mut to indicate mutable reference, or just mut to indicate it is a mutable value.
-
call_with_state is an insteresting API on the namable closures. It allows you to “mutate” the state without actually mutating anything. The above code demostrates it.
Now I need advises on the above. Do you thing I can do better?
The naming and grammar issue
Right now there are 5 different namable closure types you can use:
| function accepts |
state in struct |
type name |
| &state |
&state |
Closure |
| &mut state |
&mut state |
ClosureMut |
| &state |
state |
ClosureRef |
| &mut state |
state |
ClosureRefMut |
| state |
state |
ClosureOnce |
They are named under the usage of the closure! macro. However, I can now see that at least one of them (Closure, unfortunately the easiest one) is redundent: it didn’t add functionality to a ClosureOnce that have a reference State value. Yes, you can implement Fn and FnMut to it; but as references are Copy, you can do the same thing for ClosureOnce.
The other type ClosureMut is not the case. I have a post in the internals forum about this, but before any language changes we are not able to colapse ClosureMut with ClosureOnce, as there is no way to implement FnMut on top of a ClosureOnce when the State is not Copy.
So, we have 4 different cases to handle. But I am not very happy with there name right now. How would you like to name them and what grammar would you prefer? My dear user, I want to hear from you!