pub struct Delegate<H, O = ()> {
pub inner: H,
pub overrides: O,
}Expand description
A Handler that forwards every site to an inner handler, through the
hooks of an Overrides value.
Each site goes to the matching hook of overrides, with inner as its
extra argument, and each hook defaults to forwarding the site to inner. So
Delegate::new(h) (overrides ()) behaves exactly like h, and
Delegate::with(h, o) behaves like h except at the sites o overrides.
Delegates nest. In Delegate<Delegate<H, A>, B> the hooks of B see each
site first, and their inner is the Delegate<H, A>, which passes the site
on through A to H. At the end of the run B::finish runs first, and
A::finish runs when B::finish finishes its inner handler.
A Delegate is a plain struct of its two fields: no boxing, and every hook
call is statically dispatched.
Example (two decorators nested around a PriorHandler):
/// Logs the f64 sample sites it sees, under a name, and forwards them.
struct Log<'a>(&'static str, &'a std::cell::RefCell<Vec<String>>);
impl<H: Handler> Overrides<H> for Log<'_> {
fn on_sample_f64(
&mut self,
inner: &mut H,
addr: &Address,
dist: &dyn Distribution<f64>,
) -> f64 {
self.1.borrow_mut().push(format!("{} saw {}", self.0, addr));
inner.on_sample_f64(addr, dist)
}
}
let log = std::cell::RefCell::new(Vec::new());
let mut rng = StdRng::seed_from_u64(1);
let prior = PriorHandler { rng: &mut rng, trace: Trace::default() };
let handler = Delegate::with(Delegate::with(prior, Log("inner", &log)), Log("outer", &log));
let (_x, trace) =
runtime::handler::run(handler, sample(addr!("x"), Normal::new(0.0, 1.0).unwrap()));
assert_eq!(log.into_inner(), ["outer saw x", "inner saw x"]);
assert!(trace.get_f64(&addr!("x")).is_some()); // recorded by the PriorHandlerFields§
§inner: HThe handler that every site not overridden is forwarded to.
overrides: OThe hooks, and whatever state they keep.
Implementations§
Source§impl<H> Delegate<H>
impl<H> Delegate<H>
Sourcepub fn new(inner: H) -> Self
pub fn new(inner: H) -> Self
Wrap inner with no overrides, so every site is forwarded to it.
The result behaves exactly like inner: same values, same trace.
Example:
let model = || sample(addr!("x"), Normal::new(0.0, 1.0).unwrap());
let mut rng = StdRng::seed_from_u64(7);
let (x, _) = runtime::handler::run(
PriorHandler { rng: &mut rng, trace: Trace::default() },
model(),
);
let mut rng = StdRng::seed_from_u64(7);
let delegate = Delegate::new(PriorHandler { rng: &mut rng, trace: Trace::default() });
let (y, trace) = runtime::handler::run(delegate, model());
assert_eq!(x, y); // same seed, same draw
assert_eq!(trace.get_f64(&addr!("x")), Some(x));Source§impl<H, O> Delegate<H, O>
impl<H, O> Delegate<H, O>
Sourcepub fn with(inner: H, overrides: O) -> Self
pub fn with(inner: H, overrides: O) -> Self
Wrap inner, sending each site through the hooks of overrides first.
Example (clamp every f64 sample to [-1, 1] before the model sees it;
the trace keeps the value the inner handler drew):
struct Clamp;
impl<H: Handler> Overrides<H> for Clamp {
fn on_sample_f64(
&mut self,
inner: &mut H,
addr: &Address,
dist: &dyn Distribution<f64>,
) -> f64 {
inner.on_sample_f64(addr, dist).clamp(-1.0, 1.0)
}
}
let mut rng = StdRng::seed_from_u64(3);
let handler = Delegate::with(PriorHandler { rng: &mut rng, trace: Trace::default() }, Clamp);
let (x, _trace) =
runtime::handler::run(handler, sample(addr!("x"), Normal::new(0.0, 10.0).unwrap()));
assert!((-1.0..=1.0).contains(&x));Trait Implementations§
Source§impl<H: Handler, O: Overrides<H>> Handler for Delegate<H, O>
Every method calls the hook of the same name on overrides, passing inner.
impl<H: Handler, O: Overrides<H>> Handler for Delegate<H, O>
Every method calls the hook of the same name on overrides, passing inner.