meander

2021-08-26T12:02:59.000300Z

Meander is scary

2021-08-26T12:04:57.000600Z

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

2021-08-26T12:05:41.000900Z

@noprompt

(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 worked

2021-08-26T12:06:57.001200Z

thanks!

jgdavey 2021-08-26T14:51:36.003800Z

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?

jgdavey 2021-08-26T16:04:50.005800Z

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?

jgdavey 2021-08-26T18:40:03.006100Z

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.

Jimmy Miller 2021-08-26T20:23:57.017600Z

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.

jgdavey 2021-08-27T00:49:27.020800Z

👍

jgdavey 2021-08-27T00:50:02.021Z

I just wanted to make sure there wasn’t some idiomatic obvious thing I was missing 🙂

markaddleman 2021-08-26T15:51:27.005200Z

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

Jimmy Miller 2021-08-26T15:52:26.005600Z

That would be great!

👍 1
markaddleman 2021-08-26T19:17:26.008600Z

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?

2021-08-26T19:51:21.008700Z

The error refers to the fact that once you have !v once ?v

2021-08-26T19:51:35.008900Z

probably

markaddleman 2021-08-26T19:53:11.009100Z

Thanks, I thought meander kept those separate but I'll give it a try

2021-08-26T19:53:16.009300Z

(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]

2021-08-26T19:53:51.009600Z

it works ; )

markaddleman 2021-08-26T19:53:55.009800Z

😄 thanks!

2021-08-26T19:54:25.010Z

np

markaddleman 2021-08-26T19:55:10.010200Z

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

2021-08-26T19:55:27.010500Z

thx!

2021-08-26T19:56:01.010700Z

I'm quietly working on a major update, but I have many conceptual dilemmas

markaddleman 2021-08-26T19:57:27.010900Z

Such as? (I don't mean to pry but I'm very curious)

2021-08-26T19:57:48.011100Z

I don't know how much compatibility with datascript I should keep

markaddleman 2021-08-26T19:58:32.011300Z

I can only speak for myself: very little 🙂

2021-08-26T19:58:36.011500Z

the current use of vector as ident, as in fulcro, has many advantages but is not without disadvantages

markaddleman 2021-08-26T19:59:16.011700Z

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

2021-08-26T20:01:08.011900Z

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

markaddleman 2021-08-26T20:01:32.012100Z

I can see the value of taking a query at runtime.

markaddleman 2021-08-26T20:02:13.012300Z

It seems to me that schema can (and should?) be handled as a layer above doxa. seems pretty straightforward given that with is available

2021-08-26T20:02:17.012500Z

you know, you speak for yourself, but all the people who use doxa can sit at the same table

markaddleman 2021-08-26T20:02:29.012700Z

🙂

markaddleman 2021-08-26T20:02:38.012900Z

Is there a #doxa channel?

2021-08-26T20:02:51.013100Z

no, not yet

2021-08-26T20:03:29.013300Z

maybe it will happen if there is a need and doxa has an official release

2021-08-26T20:03:53.013500Z

for now, it's just thinktering

markaddleman 2021-08-26T20:03:56.013700Z

sounds good to me. in the meantime, I'll keep enjoying it and looking forward to your new release

2021-08-26T20:05:14.014100Z

for now, everything is happening in a separate branch

2021-08-26T20:06:10.014300Z

If you have any questions, have any ideas or find a bug, please don't hesitate to tell me

2021-08-26T20:06:39.014500Z

it is much better to work knowing that someone is watching

markaddleman 2021-08-26T20:06:45.014700Z

🙂

markaddleman 2021-08-26T20:06:54.014900Z

Yes, I agree and I'm happy to provide feedback

2021-08-26T20:07:03.015100Z

🙃

markaddleman 2021-08-26T20:12:54.015300Z

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

2021-08-26T20:18:31.015600Z

huh

2021-08-26T20:18:51.015800Z

{:mvn/version "0.0.643"}

2021-08-26T20:19:26.016Z

clj or cljs?

2021-08-26T20:19:45.016200Z

shouldn't matter, but maybe it does

markaddleman 2021-08-26T20:20:15.016400Z

clj

markaddleman 2021-08-26T20:20:43.016600Z

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 ...]))

markaddleman 2021-08-26T20:21:48.016800Z

Ah, it works in 643 but not in 602

markaddleman 2021-08-26T20:21:59.017Z

I screwed up earlier when testing against 643

2021-08-26T20:22:39.017200Z

😉

2021-08-26T20:23:18.017400Z

The worst thing about the meander is that it's a moving target

markaddleman 2021-08-26T20:24:05.017800Z

True but it's so nice that these minor hiccups are worth it 🙂

2021-08-26T20:24:11.018Z

noprompt is doing a gigantic job on its own and it is so complicated that it is difficult to help

🎉 1
2021-08-26T20:24:17.018200Z

definitely

2021-08-26T20:24:41.018400Z

I currently use meander for anything more complicated than get/get-in

👍 1
2021-08-26T23:06:45.019500Z

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

2021-08-26T23:11:42.020Z

(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