Macro environmental::environmental
source · macro_rules! environmental { ($name:ident : $t:ty) => { ... }; ($name:ident : trait @$t:ident [$($args:ty,)*]) => { ... }; ($name:ident<$traittype:ident> : trait $t:ident <$concretetype:ty>) => { ... }; ($name:ident : trait $t:ident <>) => { ... }; ($name:ident : trait $t:ident < $($args:ty),* $(,)* >) => { ... }; ($name:ident : trait $t:ident) => { ... }; }
Expand description
Declare a new global reference module whose underlying value does not contain references.
Will create a module of a given name that contains two functions:
pub fn using<R, F: FnOnce() -> R>(protected: &mut $t, f: F) -> R
This executesf
, returning its value. During the call, the module’s reference is set to be equal toprotected
. When nestingusing
calls it will build a stack of the set values. Each call towith
will always return the latest value in this stack.pub fn with<R, F: FnOnce(&mut $t) -> R>(f: F) -> Option<R>
This executesf
, returningSome
of its value if called from code that is being executed as part of ausing
call. If not, it returnsNone
.f
is provided with one argument: the same reference as provided to the most recentusing
call.pub fn using_once<R, F: FnOnce() -> R>(protected: &mut $t, f: F) -> R
This executesf
, returning its value. During the call, the module’s reference is set to be equal toprotected
when there is not already a value set. In contrast tousing
this will not build a stack of set values and it will use the already set value.
§Examples
Initializing the global context with a given value.
#[macro_use] extern crate environmental;
environmental!(counter: u32);
fn main() {
let mut counter_value = 41u32;
counter::using(&mut counter_value, || {
let odd = counter::with(|value|
if *value % 2 == 1 {
*value += 1; true
} else {
*value -= 3; false
}).unwrap(); // safe because we're inside a counter::using
println!("counter was {}", match odd { true => "odd", _ => "even" });
});
println!("The answer is {:?}", counter_value); // 42
}
Roughly the same, but with a trait object:
#[macro_use] extern crate environmental;
trait Increment { fn increment(&mut self); }
impl Increment for i32 {
fn increment(&mut self) { *self += 1 }
}
environmental!(val: Increment + 'static);
fn main() {
let mut local = 0i32;
val::using(&mut local, || {
val::with(|v| for _ in 0..5 { v.increment() });
});
assert_eq!(local, 5);
}