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 variableme
in the body is a reference to the closure itself. Without this the value will be moved to the body. Alternatively you can useref mut
to indicate mutable reference, or justmut
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!