meander

wilkerlucio 2021-09-22T19:51:59.105100Z

hello, I have another Meander puzzle 😅, this seems easier but I still hitting the wall on this:

; input data
'{:body-params {:baz int?}
  :path-params {:foo string?
                :bar uuid?}}

; expect output
'[{:name :baz, :kind :body-params, :type int?}
  {:name :foo, :kind :path-params, :type string?}
  {:name :bar, :kind :path-params, :type uuid?}]

; non-meander implementation
(defn params->fields [params]
  (reduce-kv
    (fn [out kind params]
      (if (map? params)
        (reduce-kv
          (fn [out name type]
            (conj out {:name name :kind kind :type type}))
          out
          params)
        out))
    []
    params))
with meander I tried using rewrites, but I ended up with some cardinal products, so wonder how you would tackle this

wilkerlucio 2021-09-23T13:36:57.106400Z

awesome, thank you so much, and since you asked, there is a twist on this one that I wonder if we solve strait from meander

wilkerlucio 2021-09-23T13:37:00.106600Z

this is my current code:

wilkerlucio 2021-09-23T13:37:08.106800Z

(defn params->fields [params]
  (->> (m/rewrite params
         {?k ?v & ?more}
         [& (m/cata [?k ?v]) & (m/cata ?more)]

         [?k (m/map-of !ks !vs)]
         [{:kind ?k & {:name !ks :type !vs}} ...]

         ?x ?x)
       (mapv (fn [{:keys [name] :as field}]
               (cond-> field
                 (and (coll? name) (= :opt (first name)))
                 (assoc :name (second name) :optional? true))))))

wilkerlucio 2021-09-23T13:37:30.107100Z

the mapv is to take care of optional params, here is a test including those:

(is (= (forms/params->fields
           '{:path-params {:foo   string?
                           (:opt :bar) uuid?}})
         '[{:name :foo, :kind :path-params, :type string?}
           {:name :bar, :kind :path-params, :type uuid?, :optional? true}]))

wilkerlucio 2021-09-23T13:38:09.107300Z

so in that case, it needs to extract from [:opt :name] (sometimes its (:opt :name), so not always a vector

wilkerlucio 2021-09-23T13:38:28.107500Z

and add the optional? true flag

2021-09-23T13:42:35.107700Z

to make it easier please give input and expected output

2021-09-23T13:42:43.107900Z

I don't know if I understand correctly

2021-09-23T13:45:37.108100Z

I got it, I missed something when I was reading

🆒 1
2021-09-23T14:01:34.108400Z

@wilkerlucio

(defn params->fields [params]
  (->> (m/rewrite params
         {?k ?v & ?more}
         [& (m/cata [?k ?v]) & (m/cata ?more)]

         [?k (m/map-of (m/or (m/and (m/keyword _ _ :as !ks) (m/let [!optional false]))
                             (m/and (:opt !ks) (m/let [!optional true]))) !vs)]
         [{:kind ?k & {:name !ks :type !vs :optional? !optional}} ...]
         

         {} {})))

🎉 1
2021-09-23T14:02:51.108600Z

with optional arguments, the meander is no longer concise and things get a bit messy

2021-09-23T14:05:24.108800Z

and in general, except quick hacking, I would advise you not to generally use the notation at the end of ?x ?x, you might get surprised. It's a good idea to throw an exception just like m/match

👍 2
2021-09-23T14:07:04.109Z

in the worst case ?x ?x causes rewrite return unchanged whatever it takes

noprompt 2021-09-23T20:46:41.109700Z

I just noticed the use of two & on the RHS. 🙂

2021-09-23T20:48:53.109900Z

I guess that's a good thing? ;>

😆 1
2021-09-22T20:01:01.105400Z

w8 😉

2021-09-22T20:05:42.105600Z

(m/rewrite '{:body-params {:baz int?}
             :path-params {:foo string?
                           :bar uuid?}}
  {?k ?v & ?more}
  [& (m/cata [?k ?v]) & (m/cata ?more)]
  [?k (m/map-of !ks !vs)]
  [{:kind ?k & {:name !ks :type !vs}} ...]
  ?x ?x)
;; => [{:name :baz, :type int?, :kind :body-params}
;;     {:name :foo, :type string?, :kind :path-params}
;;     {:name :bar, :type uuid?, :kind :path-params}]

2021-09-22T20:06:52.105900Z

If you have any more problems, let me know. better than crossword puzzles and sudoku

🤣 2