Skip to main content

scope

Macro scope 

Source
macro_rules! scope {
    ($key:expr, $s:expr, [$($input:expr),+ $(,)?], $body:block) => { ... };
    ($key:expr, $s:expr, [], $body:block) => { ... };
}
Expand description

Memoized composition scope with input + signal tracking.

Wraps a composable block, caching its output as long as:

  1. The explicit inputs are unchanged (by Hash comparison).
  2. No signal read during body execution has been written since last run.

When the cache is hit, the body is NOT executed -> the previously-composed View is returned instead, with proper ID and composer cursor advancement to keep sibling scopes consistent.

§Usage

use repose_core::*;

fn MyView(s: &mut Scheduler, title: &str, count: i32) -> View {
    scope!("my_view", s, [title, count], {
        Column(Modifier::new()).child((
            Text(title),
            Text(format!("Count: {count}")),
        ))
    })
}

§Signal auto-tracking

Any Signal::get() call inside the body automatically registers the scope as a dependency. When that signal is written, the scope is marked dirty and recomposed on the next frame. You don’t need to put signal values in the input list -> the reactive system handles dependencies implicitly.

let size = signal(100.0);
scope!("animated", s, [], {
    let cur = size.get();  // auto-tracked; cache invalidated on write
    Box(Modifier::new().size(cur, cur))
})

§f32/f64 in explicit inputs

Float types don’t implement Hash. For float inputs, use .to_bits():

scope!("s", s, [my_float.to_bits()], { ... })

Or -> better -> read floats from a Signal<f32> inside the body (auto-tracked).

§Compatibility with remember

remember slots consumed inside the body are tracked and properly advanced on cache hit, so sibling remember calls remain consistent.