Fork me on GitHub
#membrane
<
2023-02-10
>
elliot21:02:03

London Clojurians talk was fantastic, thanks so much for making it. Everybody needs to hear those concepts and try the framework. The ending notes on the relationship between plain data/pure fns and interoperability/composability (vs. closed parochiality, non-composability and ecosystem fragmentation/competition) are I think profound. We’ve been talking about similar concepts in #clojuredart as naive Flutter shares many of the same issues, on both desktop and mobile. Only a little exaggerated, but if the same widget + layout libraries existed for Membrane it seems to me like Membrane would already been competitive with Flutter on dev UX. This was mentioned in the talk and also seems like it goes deep--it sounds like structurally frameworks need to try to lock you into their event loop / state / callback model, as a consequence of the OOP state model: 1) OOP keeps the data in local mutable state PLOP, 2) the affordance for updating the state is executing side-effecting control flow, 3) the synchronization of the side-effects/control flow has to be managed by the event/render loop. If this is true then it seems like we can start making the reactive/data/effect engine completely decoupled from the I/O sources of events and sinks of render output (i.e. the GUI hooked up to state engine). I guess this is mostly just a +1 to the thread above https://clojurians.slack.com/archives/CVB8K7V50/p1675881605789969 but it seems important structurally! Thanks again for such thoughtful work and sharing in this area.

🙏 2
elliot21:02:04

(I think one of the main difference would be moving from “mutable state and side effects” to “events reified as data” and “state update functions (transducers?) reified as data” (i.e. an event handler is mostly just a state update function, given an event, depending upon how much external world side effects you want — although maybe even those could be reified and the runtime can run certain types of for example :http/request). But the trick is indeed converting all of the side-effecting operation functions into data structures that the runtime executes async, and passes the result back into the event-stream/handling loop (and maybe letting people manage their own loop).

phronmophobic22:02:49

> But the trick is indeed converting all of the side-effecting operation functions into data structures that the runtime executes async One of the goals behind intents is to decouple what from how. It's important not to imply too much about how (or when) an intent should be carried out. It also doesn't need to be one size fits all.

elliot23:02:29

Sorry yes, great point about like the "intent system" rather than the "effect system.". To some degree this seems like the difference between a high-level abstract operation [:notify-user], and the low-level implementation of that (at some point, bottom out at like, sending a concrete email via SMTP). But at some point it seems like abstract intent needs to be mapped/connected to a low level implementation that can concretely satisfy the intent? The CLJ-ish idiom I'm thinking of is protocols with implementations, not sure if that aligns with what you're thinking

phronmophobic23:02:36

Right, but there are contexts where they don't need to get hooked up (eg. testing). You may also have multiple implementations (either for different usage patterns or different platforms/environments).

👍 4
🔥 2
phronmophobic23:02:03

It's also fine to have a single implementation. The main idea is just to not couple the implementation with the description.

👍 2
elliot23:02:52

Is it fair to analogize that to "write against abstractions/protocols, not hard coded concretions"? (That an intent is basically always an abstract specification rather than concrete implementation instructions?) E.g. in OOP land always writing against an abstract interface where the specific implementation is always dependency injected later? (If so then it might lead to something interesting like, protocols, but a special type of protocol where they're always async dispatched and maybe awaited (or is that just futures?))

phronmophobic00:02:06

> Is it fair to analogize that to "write against abstractions/protocols, not hard coded concretions"? > > (That an intent is basically always an abstract specification rather than concrete implementation instructions?) I'm sure I'm over-philosophizing here, but the difference is a little more subtle. An intent tries to describe what the user wants. It's descriptive, rather than prescriptive. The goal is help reason about the program. This may inform how the program is written, but it might just be an informal description when discussing with a colleague at the whiteboard. It doesn't really enforce any particular programming language, construct, or library. You could use protocols. You might statically analyze the UI code at compile time and spit out a heavily optimized implementation that directly connects everything and uses mutation. You might use it as a specification for another team to figure out. In some circumstances, you might just implement all effects in event handlers with a comment that says what the user intent is. Usually, you'll probably want the structure of your code to reflect how you think about the problem, but having a data model isn't primarily about how to "do" it, but what "it" is. > (If so then it might lead to something interesting like, protocols, but a special type of protocol where they're always async dispatched and maybe awaited (or is that just futures?)) You might also do that.

elliot00:02:34

No I love it, thanks for clarifying. It seems like we’re a little getting into the territory of “what is declarative programming,” as opposed to like “imperative/procedural” programming. This seems core: > Usually, you’ll probably want the structure of your code to reflect how you think about the problem, but having a data model isn’t primarily about how to “do” it, but what “it” is. It seems like this suggests that an intent is not just an “abstraction” but an abstraction in the user’s desired conceptual domain, which usually permits a large variety of possible implementations/satisfactions of that high-level requirement. E.g. Smalltalk-y folks sometimes talk in terms of message passing and request/response, and at a high-enough level of abstraction the messages are directly an expression of the user’s actual human intent/desire domain [service :order :sandwich] and it’s wholly a separate problem to figure out how to fulfill that request in the backend — the backend has the responsibility of taking input in the user’s domain, and fulling the user’s request by internally translating it into its own implementation/execution domain, without the user/API specifying implementation instructions. (Does that sort of get at it?)

phronmophobic01:02:48

Intents are about describing what the user wants. It may allow for zero, one, or many implementations, but that's not the point. It's not about the implementation. For example, you could build a user interface for a time machine. It doesn't really matter that it might be physically impossible to implement the time travel part (but when we do, we'll be ready). Intents are useful as part of a mental model. It's a tool for thinking about the problem. Hopefully, that's also helpful for writing code, but maybe it's also just a tool for talking to product managers and UI designers.

💯 2
genekim22:02:48

PS: amazing talk, @U7RJTCH6J!! Mind expanding!

clojure-spin 2