Crate namable_closures[−][src]
This crate supports nameable closures, without requiring any language changes.
Why do we need this
The Rust language supports closures, however its concret types are
anonymous and developers cannot expect same size, and so not able to
put similar closures in containers that requires Sized
constraint.
However, there is an exception: if a closure does not refer to its
captured variables, it can be coerce to a fn
type, which is a pointer
type and it is Sized
.
This library extends this idea by requesting an additional State
field,
which is just the tuple of the captured variables. So if two closure have
the same signiture for function calls and have the same state type, they
are considered the same type.
How to use
There are 5 structures being defined, and they are correspond to different use cases.
Closure
This struct works for closures that only intended to refer to the state field, not modifying them nor owns them. However, it does own its state, so dropping this struct will drop its state as well.
This struct is created by a macro closure!
.
Example:
let add_ten:Closure<i32,(i32,),i32> = closure!(state, i, i+*state, 10); assert_eq!(add_ten(1),11); let offset:Closure<Point,(i32,i32),Point> = closure!(state, (a,b), Point::new(state.x+a,state.y+b), Point::new(10,20)); let p = offset(1,2); assert_eq!(p.x,11); assert_eq!(p.y,22);
ClosureRef
This structure works like the above, but it does not own its state.
This struct is created by a macro closure_ref!
.
Example:
let state = 10; let add_ten:ClosureRef<i32,(i32,),i32> = closure_ref!(state, i, i+10, &state); assert_eq!(add_ten(1),11); let state = Point::new(10,20); let offset:ClosureRef<Point,(i32,i32),Point> = closure_ref!(state, (a,b), Point::new(state.x+a,state.y+b), &state); let p = offset(1,2); assert_eq!(p.x,11); assert_eq!(p.y,22);
ClosureMut
This struct works for closures that will mutate its state, but would not drop its state when called. So it can be called multiple times, but will have different effects on each call. Because it still owns its state, the state will be dropped when the struct was dropped.
This struct is created by a macro closure_mut!
.
Example:
let mut accumulate:ClosureMut<i32,(i32,),i32> = closure_mut!(state, c, {*state+=c;*state}, 0); assert_eq!(accumulate(1),1); assert_eq!(accumulate(2),3);
ClosureRefMut
This struct works like the above, but it does not own its state. Furethermore, this is the
only struct in this serial that does not support Copy
and Clone
at all, because it owns
a mutable reference to its state.
This struct is created by a macro closure_ref_mut!
.
Example:
let mut state = 0; { let mut match_cnt:ClosureRefMut<i32,(i32,i32),()> = closure_ref_mut!(state, (a,b), {if a==b { *state+=1 }}, &mut state); for i in 0..10 { match_cnt(i,i*3%10); } //two matches: 0 and 5 } assert_eq!(state,2);
ClosureOnce
This struct owns its state, and will drop its state when called.
This struct is created by macros closure_once!
and closure_mut!
. The
later is useful when the state variable should be declared with mut
keyword.
Example:
let sign_on:ClosureOnce<Passwd,(String,),Result<(),io::Error>> = closure_once!(passwd, user, authenticate(user,passwd), Passwd::get_from_cache()); let auth:ClosureOnce<RoleSet,(String,Passwd),Result<(),io::Error>> = closure_once!(role_set, (user,passwd), check_user(role_set,user,passwd), RoleSet::from_config()); //Use closure_once_mut when the state should be declared with `mut` keyword let send_data:ClosureOnce<MyStream,(&[u8],),Result<usize,io::Error>> = closure_once_mut!(stream, data, stream.write_all(data), MyStream::new()); let read_data:ClosureOnce<MyStream,(&mut [u8],usize),Result<(),io::Error>> = closure_once_mut!(stream, (buf,len), stream.read_exact_ex(buf, len), MyStream::new());
Re-exports
pub use closures::Closure; |
pub use closures::ClosureMut; |
pub use closures::ClosureOnce; |
pub use closures::ClosureRef; |
pub use closures::ClosureRefMut; |
Modules
closures |
Macros
closure |
Create a nameable closure object with an immutable state |
closure_mut |
Create a nameable closure object with a mutable state |
closure_once |
Create a nameable closure object consumes a state when called |
closure_once_mut |
Create a nameable closure object consumes a mutable state when called |
closure_ref |
Create a nameable closure object refers to an immutable state |
closure_ref_mut |
Create a nameable closure object refer to a mutable state |