Fork me on GitHub
#meander
<
2022-01-23
>
lvh02:01:37

Hi! I’m using meander to do this:

(m/search inferred-schemata
    (m/and
     (m/scan
      {:create-table ?table
       :with-columns (m/scan [?field _type])})
     (m/let [?idx (condp re-find (->snake-str ?field)
                    #"uuid$" :exact
                    #"name$" :nocase
                    #"^alias" :nocase
                    nil)]))

    (let [table (->snake-str ?table)
          field (->snake-str ?field)
          index (format "idx_%s_%s" table field)
          tail (when (= ?idx :nocase) " COLLATE NOCASE")]
      [(format "CREATE INDEX %s ON %s (%s)%s;" index table field tail)]))
However, I only want to match when (some? ?let) — how can I do that for an m/let introduced variable?

lvh02:01:26

I’m able to hack around it fine:

(->>
   (m/search inferred-schemata
     (m/and
      (m/scan
       {:create-table ?table
        :with-columns (m/scan [?field _type])})
      (m/let [?idx (condp re-find (->snake-str ?field)
                     #"uuid$" :exact
                     #"name$" :nocase
                     #"^alias" :nocase
                     nil)]))
     (when ?idx
       (let [table (->snake-str ?table)
             field (->snake-str ?field)
             index (format "idx_%s_%s" table field)
             tail (when (= ?idx :nocase) " COLLATE NOCASE")]
         [(format "CREATE INDEX %s ON %s (%s)%s;" index table field tail)])))
   (remove nil?))
but I’d love to be able to just write it in meander

noprompt04:01:50

For this kinda thing m/with is gonna help

noprompt04:01:52

(defn test []
  (m/search {:create-table "foo"
             :with-columns {"foo" "bar"}}
    (m/with [%index (m/or (m/let [?idx :exact, ?tail ""]
                            (m/re #".*uuid"))
                          (m/let [?idx :nocase, ?tail " COLLATE NOCASE"]
                            (m/re #"^alias.*|.*name$")))
             %table (m/app ->snake-str ?table)
             %field (m/app ->snake-str ?field %index)]
      {:create-table %table
       :with-columns (m/scan [%field _type])})
    (let [index (format "idx_%s_%s" ?table ?field)]
      [(format "CREATE INDEX %s ON %s (%s)%s;" index ?table ?field ?tail)])))
(do
  (def ->snake-str
    (constantly "fooname"))
  (test))
;; =>
(["CREATE INDEX idx_fooname_fooname ON fooname (fooname) COLLATE NOCASE;"])

(do 
  (def ->snake-str
    (constantly "aliasfoo"))
  (test))
;; =>
(["CREATE INDEX idx_aliasfoo_aliasfoo ON aliasfoo (aliasfoo) COLLATE NOCASE;"])

(do
  (def ->snake-str
    (constantly "foouuid"))
  (test))
;; =>
(["CREATE INDEX idx_foouuid_foouuid ON foouuid (foouuid);"])

noprompt04:01:05

I made up ->snake-str here to test three regex cases.

noprompt04:01:32

The nil case comes free by virtue of search failure not returning the results.

noprompt04:01:34

In the two m/let cases we can bind ?tail since

tail (when (= ?idx :nocase) " COLLATE NOCASE")
from the code you pasted.

noprompt04:01:39

I hope I got this right or at least close. 🙂

noprompt04:01:16

My wife made a sushi bake and I ate a lot of it so I'm kinda loopy on the account of a blood sugar spike. 😛

lvh18:01:10

ah gotcha yep that makes sense, thanks!