meander

All things about https://github.com/noprompt/meander Need help and no one responded? Feel free to ping @U5K8NTHEZ
grounded_sage 2020-02-21T00:19:52.305900Z

It can handle it with 6gb in heap size haha. Going to use sqlite as you suggested.

simongray 2020-02-21T12:03:21.307800Z

What’s the idiomatic way to match an optional value? e.g. I want

(m/rewrite [:list {:title "some title"} [:item "glen"] [:item "torben"]]
           [:list ?attr . [:item !x] ...] [:ul ?attr . [:li !x] ...])
to also work if the example hiccup input doesn’t contain an attribute map.

simongray 2020-02-21T12:58:17.308300Z

@aisamu can you post it here instead, please? That site is asking me to make an account to see the content.

aisamu 2020-02-21T12:59:44.308600Z

(That's zulip, it maintains a searchable mirror of what happens here). I'll try to find it on clojurians-log

aisamu 2020-02-21T13:03:38.308900Z

It looks like the logbot for clojurians wasn't invited here, so zulip's the only way. It's actually pretty nice, and sometimes I wish discussions happened there instead (because the threading is nicer and we don't lose history)

simongray 2020-02-21T15:06:00.310200Z

defsyntax doesn’t work in ClojureScript? I’m using rewrite in the same namespace just fine… 😕

simongray 2020-02-21T15:06:00.310300Z

------ WARNING #1 - :undeclared-var --------------------------------------------
 File: /Users/rqf595/Code/facsimile/dev/user.cljs:50:1
--------------------------------------------------------------------------------
  47 |                            (reduced comp)))]
  48 |     (reduce-kv (matching-comp node) nil pred->comp)))
  49 | 
  50 | (m/defsyntax number
-------^------------------------------------------------------------------------
 Use of undeclared Var meander.syntax.epsilon/*form*
--------------------------------------------------------------------------------
  51 |   ([] `(number _#))
  52 |   ([pattern] (if (m/match-syntax? &env)
  53 |                `(m/pred number? ~pattern)
  54 |                &form)))
--------------------------------------------------------------------------------

------ WARNING #2 - :undeclared-var --------------------------------------------
 File: /Users/rqf595/Code/facsimile/dev/user.cljs:50:1
--------------------------------------------------------------------------------
  47 |                            (reduced comp)))]
  48 |     (reduce-kv (matching-comp node) nil pred->comp)))
  49 | 
  50 | (m/defsyntax number
-------^------------------------------------------------------------------------
 Use of undeclared Var meander.syntax.epsilon/*env*
--------------------------------------------------------------------------------
  51 |   ([] `(number _#))
  52 |   ([pattern] (if (m/match-syntax? &env)
  53 |                `(m/pred number? ~pattern)
  54 |                &form)))
--------------------------------------------------------------------------------

------ WARNING #3 - :undeclared-var --------------------------------------------
 File: /Users/rqf595/Code/facsimile/dev/user.cljs:52:19
--------------------------------------------------------------------------------
  49 | 
  50 | (m/defsyntax number
  51 |   ([] `(number _#))
  52 |   ([pattern] (if (m/match-syntax? &env)
-------------------------^------------------------------------------------------
 Use of undeclared Var meander.epsilon/match-syntax?
--------------------------------------------------------------------------------
  53 |                `(m/pred number? ~pattern)
  54 |                &form)))
  55 | 
  56 | (m/rewrite [:glen {:data-ref "glen"}]
--------------------------------------------------------------------------------

------ WARNING #4 - :dynamic ---------------------------------------------------
 File: /Users/rqf595/Code/facsimile/dev/user.cljs:50:1
--------------------------------------------------------------------------------
  47 |                            (reduced comp)))]
  48 |     (reduce-kv (matching-comp node) nil pred->comp)))
  49 | 
  50 | (m/defsyntax number
-------^------------------------------------------------------------------------
 meander.syntax.epsilon/*form* not declared ^:dynamic
--------------------------------------------------------------------------------
  51 |   ([] `(number _#))
  52 |   ([pattern] (if (m/match-syntax? &env)
  53 |                `(m/pred number? ~pattern)
  54 |                &form)))
--------------------------------------------------------------------------------

------ WARNING #5 - :dynamic ---------------------------------------------------
 File: /Users/rqf595/Code/facsimile/dev/user.cljs:50:1
--------------------------------------------------------------------------------
  47 |                            (reduced comp)))]
  48 |     (reduce-kv (matching-comp node) nil pred->comp)))
  49 | 
  50 | (m/defsyntax number
-------^------------------------------------------------------------------------
 meander.syntax.epsilon/*env* not declared ^:dynamic
--------------------------------------------------------------------------------
  51 |   ([] `(number _#))
  52 |   ([pattern] (if (m/match-syntax? &env)
  53 |                `(m/pred number? ~pattern)
  54 |                &form)))
--------------------------------------------------------------------------------

------ WARNING #6 - :undeclared-var --------------------------------------------
 File: /Users/rqf595/Code/facsimile/dev/user.cljs:50:1
--------------------------------------------------------------------------------
  47 |                            (reduced comp)))]
  48 |     (reduce-kv (matching-comp node) nil pred->comp)))
  49 | 
  50 | (m/defsyntax number
-------^------------------------------------------------------------------------
 Use of undeclared Var meander.syntax.epsilon/global-expander-registry
--------------------------------------------------------------------------------
  51 |   ([] `(number _#))
  52 |   ([pattern] (if (m/match-syntax? &env)
  53 |                `(m/pred number? ~pattern)
  54 |                &form)))
--------------------------------------------------------------------------------

jimmy 2020-02-21T15:12:27.311800Z

@simongray I will take a look into what is going on. I can't remember off the top of my head if defsyntax needs to be defined in clojure like a macro and then used in clojurescript or not. Just blanking out on that at the moment. (I think that might be the case)

jimmy 2020-02-21T15:19:28.311900Z

It depends on what you are doing. That is why there isn't a one size fits all solution right now. But we have thought about making a nice shortcut for it.

(m/rewrite [:list [:item "glen"] [:item "torben"]]
  [:list (m/or {:as ?attr} (m/let [?attr {}])) . [:item !x] ...] 
  [:ul ?attr . [:li !x] ...])
For you example you can do this. One thing to note is my addition of the {:as ?attr} this makes sure we are only matching maps. If you are doing this a lot in a match you can pull it out into a with statement.
(m/rewrite [:list [:item "glen"] [:item "torben"]]
  (m/with [%attr (m/or {:as ?attr} (m/let [?attr {}]))]
    [:list %attr . [:item !x] ...] 
    [:ul ?attr . [:li !x] ...]))

jimmy 2020-02-21T15:20:24.312300Z

You can also just make multiple clauses if that is more clear.

jimmy 2020-02-21T15:24:25.313400Z

@simongray Yeah, you should treat defsyntax just like you would a macro. You define it in a clojure file, require that file in your clojurescript and you can use it in your clojurescript matches.

simongray 2020-02-21T15:26:00.313500Z

thanks! macros in CLJS always trip me up :)

simongray 2020-02-21T15:26:32.313700Z

thank you so much!

jimmy 2020-02-21T15:31:20.317200Z

I agree 100%

jimmy 2020-02-21T15:32:01.318700Z

Might be good to give a better error for this. I'll see what we can do about that.

1👍1😊
markaddleman 2020-02-21T15:32:48.320100Z

My data can match one of two patterns using m/or. Regardless of which pattern it matches, the output requires a single lvar. One of the two patterns needs a join so it has an extra lvar for "internal" join purposes. Meander requires that every branch of the m/or declare the same lvars even though, in this case, the "internal" lvar is never used anywhere but its branch. This forces some minor, unnecessary complexity in the other branch. It's a small thing but could meander be enhanced to handle this case more gracefully?

simongray 2020-02-21T15:33:56.321100Z

One more question before I head home for the weekend: say I want to match only the hiccup vector with an attr containing certain keys, e.g.

{:data-ref ?ref :data-type ?type}
The default in meander seems to be that any maps will match and the keys are solely used for capturing values. Is there no sugar for matching against a map containing certain keys?

jimmy 2020-02-21T15:36:04.321400Z

If you can give an example that would be super helpful. I think understand what you are saying, but seeing something concrete helps a lot.

jimmy 2020-02-21T15:38:20.322300Z

{:data-ref (m/some ?ref) :data-type (m/some ?type)}
If you don't actually care about capturing the values you can just use {:my-key (m/some)}

simongray 2020-02-21T15:39:29.322400Z

I do care, though 😉

jimmy 2020-02-21T15:42:26.322600Z

Yeah, so if you do care just use (m/some ?my-var).

jimmy 2020-02-21T15:43:19.323Z

There you will only match maps will non-nil values for those keys.

jimmy 2020-02-21T15:46:55.323200Z

If I have an example, I can disable some checks, run things through and think more about what problems not having the logic var in both branches might cause. It could be that we are overly restrictive and there is some less strict property that is still safe. But I'm not 100% sure.

simongray 2020-02-21T15:48:30.323400Z

Thank you. Sorry for being a bit clueless. I only started usig meander a couple of hours ago (after rewatching your excellent strange loop talk).

jimmy 2020-02-21T15:49:38.323600Z

No worries at all. There is a lot to learn and I'm always happy to help out. I'm glad that you enjoyed the talk 🙂

markaddleman 2020-02-21T15:49:52.323800Z

The let and ?join-key in the second or branch isn't strictly necessary

jimmy 2020-02-21T15:58:39.324600Z

Super helpful. Thanks, I'll look into things and think about what we might be able to do. If you don't hear back from me, feel free to either bug me again or file a github issue.

1👍
jimmy 2020-02-21T16:01:36.324900Z

So I will say, that I just checked it won't be as easy as changing the check. As it stands now, without that check the code we generate will not work. I don't think this is a fundamental limitation, but one we do have right now.

markaddleman 2020-02-21T16:08:30.325100Z

No worries, it's not a big thing - just a thing 🙂

markaddleman 2020-02-21T16:09:52.325300Z

One related thing : Can the check message include the missing vars? Meaning, if I didn't have the let in the second branch, could the message say, "Yo! You're missing ?join-key in one of the or branches"

jimmy 2020-02-21T16:17:22.325500Z

The variables that are missing are in the ex-info. Not sure your setup, but I see them when I run your code:

{:env {:lvrs #{}, :mvrs #{}, :refs {}, :path []},
 :problems
 [{:pattern (m/scan {(m/some "a3") ?value}), :absent #{?join-key}}],
 :syntax-trace
 [(m/or
   (m/and
    (m/scan {"join" ?join-key, (m/some "a1") ?value})
    (m/scan {"join" ?join-key, (m/some "a2") ?value}))
   (m/scan {(m/some "a3") ?value}))]}

jimmy 2020-02-21T16:19:10.325800Z

So, I think we could possibly make this work for rewrite/rewrites, but not match/search. Because we'd have to know that on the rhs you don't use that logic variable and the right hand side of search/match are unanalyzed.

markaddleman 2020-02-21T16:19:48.326Z

Ah, I didn't think to look in the ex-info. Thx

markaddleman 2020-02-21T16:21:23.326200Z

That makes sense. Other than performance, is there a reason to prefer match/search over rewrite/rewrites?

jimmy 2020-02-21T16:32:48.326400Z

Not sure you'd see too much of a performance difference right now. Rewrite can eventually be faster because we can optimize more. Really it is just a question of if you want substitution on the right hand side (rewrite) or arbitrary clojure code (match).