Skip to content

Instantly share code, notes, and snippets.

@raphlinus
Last active May 31, 2022 13:30
Show Gist options
  • Save raphlinus/c31cfb6dee922e8f1e9b96d0e131a916 to your computer and use it in GitHub Desktop.
Save raphlinus/c31cfb6dee922e8f1e9b96d0e131a916 to your computer and use it in GitHub Desktop.
Sketch of ideas for lasagna architecture

Pure lasagna:

trait AppLogic {
    fn run(&mut self, actions: Vec<(Id, Box<dyn Any>)>) -> Mutation;
}

A callback based approach to the actions:

struct Callbacks<T> {
    callbacks: HashMap<Id, Box<dyn FnMut(Box<dyn Any>, &mut T)>>;
}

impl Callbacks {
    fn add(&mut self, id: Id, f: FnMut(Box<dyn Any>, &mut T)) {...}

    fn delete(&mut self, id) {...}

    /// Maybe single action
    fn run(&mut self, actions: Vec<(Id, Box<dyn Any>)>, data: &mut T) {...}
}

trait Component {
    fn run(&mut self, callbacks: &mut Callbacks<Self>) -> Mutation
}

struct App<T: Component> {
    callbacks: Callbacks<T>,
    root: T,
}

impl AppLogic for App {
    fn run(&mut self, actions: Vec<(Id, Box<dyn Any>)>) -> Mutation {
        self.callbacks.run(actions, &mut self.root);
        root.run(&mut self.callbacks);
    }
}

Slight tweak to this: Component::run takes a callback context with add and delete methods (and has a &mut reference to the actual callback hashmap). To run a subcomponent, parent component lenses this context.

Vdom<T>: nodes contain callbacks. Reconciliation updates the callbacks context, returns Mutation.

trait VdomComponent {
    fn run(&mut self) -> Vdom<Self>;
}

To wire in subcomponents. Add callbacks context to this run method, not for self use, only by use of subcomponents. Call Component::run, get Mutation back. One node type of Vdom is this mutation.

Other ideas: callback returns a local action type, unit at root. Lensing of subcomponent callbacks can consume this.

Elm-style events. Component has Event associated type, event(&mut self, event: Self::Event) method. Hashtable is not callbacks that mutate the component, but rather "half-lenses" that take Box<dyn Any> action to component's event type.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment