Fork me on GitHub
#meander
<
2023-10-04
>
Zachary22:10:23

I have a search query, something like:

(let [k :my-key]
  (m/search foo-records
    (m/scan {:my-val ?val k true})
    ?val))
Where I’m trying to pass a key in through a let binding, but it doesn’t seem to be captured. Is there a way to pass in some structure to be pattern matched?

Coby Tamayo05:10:49

I'm not completely sure what you're asking, but I noticed you're not using k in your pattern at all

Zachary22:10:42

Right, typo… meant for the :my-key in the body to be the k. Edited.

Coby Tamayo04:10:43

ohhhh I see what's happening...but it threw me off for a second too. Since m/search and friends allow for arbitrary symbols in your form (like ?val is here), it's parsing k as such a symbol as well. You can unquote it with ~ to accomplish what you want though:

(let [k :my-key]
  (m/search [{:my-val 5 :my-key true :x :y}]
    (m/scan {:my-val ?val ~k true})
    ?val))
See operator https://github.com/noprompt/meander/blob/epsilon/doc/operator-overview.md#unquote.

Coby Tamayo04:10:22

Poking at this helped me gain some intuition for how Meander works...consider that without the let binding, it doesn't throw an error to have k (not unquoted) appear in the form:

(m/search {:my-val 5 :my-key true}
  {:my-val ?val k true} ?val)
However, if you try to return k in your result, it'll throw a syntax error: Unable to resolve symbol: k in this context:
(m/search {:my-val 5 :my-key true}
  {:my-val ?val k true} [?val k])
This kinda makes sense since k is recognizably not a logic or memory var, but this is definitely a sharp edge. @U06MDAPTP is this by design? I would expect that the same logic that decides whether or something can be bound in a LHS expr should match the logic for the bindings that end up in a RHS expr as well. If there is no way to get a non-logic (/etc.) variable "out" as part of a RHS expr I would expect such a variable to get flagged as a syntax error on the LHS...but maybe I am just missing something. 🙂

Coby Tamayo04:10:12

hmmm maybe it has to work this way in order to match on symbols?

(m/search {:my-val 5 'sym true}
  {:my-val ?val sym ?sym} [?val ?sym])