Meander is scary
I think I'm starting to understand something, that I've licked a bit and can do things, and then it turns out that it's not true
(let [q '[:find ?e ?age :in ?name :where [?e :name ?name] [?e :age ?age]]]
(m/rewrite q
[(m/keyword _ _ :as ?keyword) & ?args & (m/cata ?out)]
{?keyword ?args & ?out}
[] {}))
I had to write it down on a piece of paper to understand how and why it workedthanks!
Hi! Long time, no chat, folks. 🙂 Anyway, I’m working on improving test failure messages using meander. Right now, a really big pattern that does not match the subject under test is just printing out the full pattern and full data, but I have a feeling that can be improved. Specifically, I’m wondering if there are any ways to decompose a pattern into smaller bits, such that the “matching” parts of a pattern could be separated from the “non-matching” parts. Does this make sense?
To expound a bit, let’s say I’m trying to match a map pattern:
(let [expr {:present "yes"
"notkeyword" "missing"}]
(m/find expr
{:present "yes"
:missing "no"
(m/pred keyword? ?k) "missing"}
true
_
false))
This returns false, as expected. What I’d love is to return the portion of the pattern map that doesn’t unify, like:
{(m/pred keyword? ?k) "missing"
:missing "no"}
Does this make sense?For now, I’m mapping each mapentry of the map pattern into individual “patterns”, and then seeing which work with m/find, and which don’t. If they don’t, I merge them back into a pattern to display the “missing” map entries.
Yeah, that would definitely be cool to have. Not really sure we can make something like that happen given the current setup. We've talked about build some separate explainer for why a pattern didn't match.
👍
I just wanted to make sure there wasn’t some idiomatic obvious thing I was missing 🙂
hey @noprompt @jimmy - regarding https://clojurians.slack.com/archives/CFFTD7R6Z/p1629361502065800 - Would it be helpful if I updated meander's deps.edn with a packaging task? I'll have some time this weekend and happy to do it if it'll help
That would be great!
I have a map and a vector. I'd like to gather up all of the values within the vector that are also keys in the map. It's natural to write
(let [m {:a "a", :b "b'"}
v [:a :b :c]]
(m/rewrite [m v]
[?m (m/gather (m/and (m/pred contains? ?m ?v)
!v))]
[!v ...]))
but, it doesn't work: Zero or more patterns may not have references to unbound logic variables. I've tried many different varieties of the above but it's always one error or another.
Any ideas?The error refers to the fact that once you have !v once ?v
probably
Thanks, I thought meander kept those separate but I'll give it a try
(let [m {:a "a", :b "b'"} v [:a :b :c]]
(m/rewrite [m v]
[?m (m/gather (m/pred #(contains? ?m %) !xs))]
[!xs ...]))
;; => [:a :b]it works ; )
😄 thanks!
np
btw, I really like what you're doing with doxa. I have been working through https://github.com/fulcro-community/fulcro-exercises and doxa makes handling the normalized database much nicer
thx!
I'm quietly working on a major update, but I have many conceptual dilemmas
Such as? (I don't mean to pry but I'm very curious)
I don't know how much compatibility with datascript I should keep
I can only speak for myself: very little 🙂
the current use of vector as ident, as in fulcro, has many advantages but is not without disadvantages
I'm exclusively interested in doxa as a convenience for fulcro. I'm sure there are other use cases but, again, I can only speak for myself
I don't really need it either, but a couple of people have asked about schema, or the possibility that q is not a macro and can take a query on runetime
I can see the value of taking a query at runtime.
It seems to me that schema can (and should?) be handled as a layer above doxa. seems pretty straightforward given that with is available
you know, you speak for yourself, but all the people who use doxa can sit at the same table
🙂
Is there a #doxa channel?
no, not yet
maybe it will happen if there is a need and doxa has an official release
for now, it's just thinktering
sounds good to me. in the meantime, I'll keep enjoying it and looking forward to your new release
for now, everything is happening in a separate branch
If you have any questions, have any ideas or find a bug, please don't hesitate to tell me
it is much better to work knowing that someone is watching
🙂
Yes, I agree and I'm happy to provide feedback
🙃
regarding the meander example you provided, what build of meander are you using? I tried your solution in 602 and 643. It didn't work in either
huh
{:mvn/version "0.0.643"}
clj or cljs?
shouldn't matter, but maybe it does
clj
Double checking that this is what works for you:
(let [m {:a "a", :b "b'"} v [:a :b :c]]
(m/rewrite [m v]
[?m (m/gather (m/pred #(contains? ?m %) !xs))]
[!xs ...]))
Ah, it works in 643 but not in 602
I screwed up earlier when testing against 643
😉
The worst thing about the meander is that it's a moving target
True but it's so nice that these minor hiccups are worth it 🙂
noprompt is doing a gigantic job on its own and it is so complicated that it is difficult to help
definitely
I currently use meander for anything more complicated than get/get-in
I wonder how it can be written better and more efficiently
(m/rewrite {:a 1 :db/id 1}
{(m/keyword _ "id" :as ?k) ?v & _}
[?k ?v]
{_ _ & ?more}
(m/cata ?more)
_ false)
in this form is 10x slower than a simple clojure loop(m/rewrite {:a 1 :db/id 1}
(m/scan [(m/keyword _ "id" :as ?k) ?v])
[?k ?v]
_ false)
this, on the other hand, is only 3x slower