Fork me on GitHub
#meander2020-02-21
>
simongray15:02:00

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

simongray15:02:00

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

jimmy15:02:27

@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)

jimmy15:02:25

@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.

simongray15:02:00

thanks! macros in CLJS always trip me up :)

jimmy15:02:20

I agree 100%

jimmy15:02:01

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

👍 1
😊 1
markaddleman15:02:48

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?

jimmy15:02:04

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.

jimmy15:02:55

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.

markaddleman15:02:52

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

jimmy15:02:39

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
jimmy16:02:36

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.

markaddleman16:02:30

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

markaddleman16:02:52

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"

jimmy16:02:22

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

jimmy16:02:10

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.

markaddleman16:02:48

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

markaddleman16:02:23

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

jimmy16:02:48

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

simongray15:02:56

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?

jimmy15:02:20

{: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)}

simongray15:02:29

I do care, though 😉

jimmy15:02:26

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

jimmy15:02:19

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

simongray15:02:30

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

jimmy15:02:38

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 🙂