Wow @hiskennyness, you have quite the knack for writing documentation! Thank you very much both for matrix and for making it so clear what's going on and how to use it. :D I had to dive into the circuit board code this week, so I'm just now jumping back into my bluetooth mx library. I really like how it's going so far. Before I had written a wrapper (I have since scrapped) without mx, and even this early on it is already much simpler! I think the next thing I need to figure out is a nested matrix.
Thx! I actually find doc hard!! We all loved Matrix when we stumbled into creating it back in the 90s, and this is the first time I have made a concerted effort to share it instead of just using it for my own (intense) projects. Maybe a half-dozen others have discovered/loved Matrix over the years. So talk to me about this "nested Matrix". It sounds like what I am documenting next! The so-called "family" API. It works really painlessly. But I will hold off until i hear more. If you need a laugh, I got delayed on this exploring iPad drawing tools so I could diagram the family thing, though it is not really necessary. But the re-frame doc inspired me to step up my illustration game. :)
Sweet! I'm a big fan of making things visual. Alright, I had planned to revamp this a little after working through your stream tutorial, but I'll share what I've got so far and try to describe where I want to go with it:
Sneak preview, @zenflowapp: https://github.com/kennytilton/matrix/blob/main/cljc/matrix/test/tiltontec/model/kids_test.cljc I am surprised I did only one test. I have other repos I can check. Anyway, I am documenting all this next.
Aha! I should have known to go perusing through the tests :)
Hmm, I am looking at your code now. I suspect the Family thing may apply, but am not sure. I guess bluetooth devices will come and go, yes? Let me read some more. I am so used to GUIs where there is a ton of hierarchical structure, and especially a need for one node to care about one or more other nodes, that I am stuck in familiythink. Reading....
:candidates is the one I'm expecting to be a child matrix. that actually may need to be renamed - it's the receiving cell for the ephemeral scan results. :device-candidates would maybe be a new one that is a child matrix.
Oh and the one and only comment was an out-of-date note to self :P
Working on applying your test code example...
Agreed. I am thinking candidates can be a formula that reads :scan-results and does a diff with its own _cache (glad I just covered that!) to see if candidates have been gained or lost.
Then I would make a matrix object for the candidate, and have a connection property "compute" a connection, and then have a :watch on that property kick off the "listen".
Shooting from the hip. Still reading absorbing.
Yes, I spotted a couple of edits. Thx, keep em coming.
btw, the candidates property so far seems fine as a vector, no crying need for the family class. But agreed on what I think you meant by "nested Matrix": each candidate might deserve its own MX object.
Do I gather that connections will be candidates that successfully connect?
I started to make it as a vector as I was thinking about it, but then I realized I wanted to to some reactive calculations for each of them. Yep! I'm not focused on the multiplicity for my current use-case, but I do want this to be a library I can reuse across projects.
The one thing that Family might contribute is that it knows how to watch a collection, recognize known elements and keep them, and build new children for unknown elements. This is like React with its :key on collections being efficient about maintaining widget lists.
For some (future) apps I'd like to have a reactive f/mx that shows/updates candidates based on what is current.
I call the class :family-values, if you know the movie. 🙂 The property :values would hold scan results. Then we provide a key function and factory function. The family-values code uses the key to discern which :values have come or gone, and uses the factory function on new values to generate new children, in this case candidates.
:par -> parent?
Yep. I do not like typing. 🙂
Haha no I'm mostly movie illiterate :P I used to be a huge fan of very descriptive variable names... and then I met tailwind-css :P Edit: A little harder to learn up-front -> A whole lot faster once learned :)
In a multi-MX app, every MX but the root has a :par parent, and zero or more :kids. But f/mx is forcing us into letting any property of an MX hold other MXes,
I am huge on /not/ abbreviating anything shorter than seven characters, unless it will be appearing all over the code and become utterly familiar to the developer.
Movie illiterate? No Spinal Tap? We need to talk. 🙂
Yeah, exactly. Haha okay :P
Getting back to your app
I started to make it as a vector as I was thinking about it, but then I realized I wanted to to some reactive calculations for each of them.
Yes. Reactive is a slippery slope. It naturally invites us to make things declarative/functional. Good to just jump into it.Yeah I'm already wanting to port it to Carp for my embedded work :D ... probably not realistically have time to do that in the near future.
Here's a headstart: https://github.com/kennytilton/cells
Oh, so :kids isn't/wasn't just an arbitrary (conventional) value until f/mx? I was writing this:
:device-candidates (cF (the-kids
(when (md-get me :scan-candidates)
(md/make
:manufacture-data (cF
)))))Hmmm. That just might work! 🤣 Lemme think...
The good thing is that the macro the-kids does take care of providing the parent for the :par property of each kid, so we are in a position to support one of the key features of MX: we can easily navigate the universe from anywhere in the universe, to get properties we need either for formulas or observers.
When I did RoboCells, a virtual RoboCup player, the family hack was applied a few places. A team was a family of players, a strategy was a family of tasks, prolly more. Trees are great. 🙂
Sweet! Sounds like a project that would be a really headache-prone otherwise made fun by using matrix :)
Alright about Family knowing "how to watch a collection" --- is this an example of that? https://github.com/kennytilton/matrix/blob/main/cljc/matrix/test/tiltontec/model/core_test.cljc#L72 ... Might be time for my nap ... that embedded code was a rushed-project and I've been working way too many hours in a row trying to figuring out a C SDK codebase. :P
Hold on, draft-code almost ready ...
looking at fm-2 in the meantime....
:device-candidates
(cF (the-kids
(when-let [scan-candidates (md-get me :scan-candidates)]
(mapv (fn [^ble/ScanResult sr]
(md/make
:device-name (cF)
:manufacturer-data (cF
(mget me :device))))
scan-candidates))))
^^^ like this?
A bit of noise in there
I'll check that out ^^^. This is all I see of family-values, no tests though: https://github.com/kennytilton/matrix/blob/4319530a7c1c110a6f8207394ee79655170ecd2f/cljc/matrix/src/tiltontec/model/core.cljc#L361
Hmm
Performing hot reload...
I/flutter (30664): :on-reload
I/flutter (30664): :got-scan-result
E/flutter (30664): [ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: Exception: jz/err> Instance of 'strifn18695hm$1' change to slot not mediated by cell and map lacks slot :candidates
E/flutter (30664): ;; but has (:host :device-candidates :parent :scan-candidates :scan-results :cells-flushed :target :scanning? :connections :eager-connect)I like that your errors even read well after dart compilation!
If you are OK with always regenerating device-candidate, ie, if they are lightweight, that looks fine. Let me see if I put that kid-values-kids to use somewhere.
btw, I have gotten pretty quick at porting Matrix. Two weeks for a new language, but Carp looks cool. What's our budget? 🙂
Looks like an attempt to (mset! x :candidates) and there is no such slot.
The error is whining about not finding an input cell and then going on to whine that the whole slot does not exist. 🤣
Haha I'm pretty early on in the running-my-own business thing, so not super-high, but I'll dm you when the time comes :) Oh yes sorry I meant that only as an example of how I liked your error messages. I just forgot to rename it across the board.
Ah, well that arose because another noob could not parse the original error, and it occurred to me that I could be a lot more helpful with such errors. Glad I did, turns out there were only a few to handle.
Nice!
This is on the pure matrix side: https://github.com/kennytilton/matrix/wiki/usage-errors
Ah, kid-values-kids in action: https://github.com/kennytilton/matrix/blob/4319530a7c1c110a6f8207394ee79655170ecd2f/cljc/whoshiring/src/whoshiring/job_list.cljs#L150