This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2020-05-01
Channels
- # announcements (3)
- # babashka (17)
- # beginners (163)
- # bristol-clojurians (1)
- # calva (18)
- # chlorine-clover (17)
- # clj-kondo (13)
- # cljs-dev (50)
- # cljsjs (3)
- # cljsrn (13)
- # clojure (218)
- # clojure-dev (5)
- # clojure-europe (9)
- # clojure-italy (10)
- # clojure-nl (8)
- # clojure-uk (107)
- # clojurescript (25)
- # conjure (163)
- # cursive (63)
- # data-science (9)
- # datomic (38)
- # docker (1)
- # figwheel (34)
- # figwheel-main (3)
- # fulcro (15)
- # graalvm (1)
- # helix (12)
- # jobs (3)
- # juxt (5)
- # kaocha (3)
- # lein-figwheel (2)
- # leiningen (6)
- # luminus (2)
- # malli (1)
- # meander (12)
- # nrepl (4)
- # rdf (2)
- # re-frame (2)
- # reagent (7)
- # reitit (5)
- # remote-jobs (2)
- # rum (1)
- # shadow-cljs (65)
- # spacemacs (27)
- # tools-deps (18)
- # vim (19)
- # xtdb (2)
Hi everybody, I'm really excited by the potential of meander and I'm trying to figure out if I can make my code more transparent by using meander for data science.
I'm getting data in the shape of [{:a [1 2]}]
and I need to transform it such that it becomes [{:a 1 :idx-row 0 :idx-vec 0} {:a 2 :idx-row 0 :idx-vec 1}]
which I can plot with vega-lite. So I need to unpack and index the elements of the vectors and add row indices (`:idx-row`).
I've written the unpack-and-index-vec-from-seq-of-map
function to get it in the right shape, but I'd like to do this with meander.
(defn unpack-and-index-vec-from-seq-of-map [vec-key seq-of-maps]
(->> seq-of-maps
(map-indexed (fn [idx-row m] (assoc m :idx-row idx-row)))
(map (fn [row]
(map-indexed
(fn [idx-vec vec-element]
(assoc row vec-key vec-element :idx-vec idx-vec))
(get row vec-key))))
(apply concat)))
(def test-data [{:b 2 :a [2 3]} {:b 3 :a [4 5]}])
(unpack-and-index-vec-from-seq-of-map :a test-data)
;; =>
;; ({:b 2, :a 2, :idx-row 0, :idx-vec 0}
;; {:b 2, :a 3, :idx-row 0, :idx-vec 1}
;; {:b 3, :a 4, :idx-row 1, :idx-vec 0}
;; {:b 3, :a 5, :idx-row 1, :idx-vec 1})
I'm a bit overwhelmed with all the possibilities I have in meander. Can you help me figure out how this would work?
cheersHi @U5309L9JP, Here is one way:
(m/rewrite [{:b 2 :a [2 3]} {:b 3 :a [4 5]}]
(m/and
[{:a [!x !y] & (m/and !m1 !m2)} ..?n]
(m/let [((m/and !ns1 !ns2) ...) (range ?n)]))
[{:a !x
:idx-row !ns1
:idx-vec 0
& !m1}
{:a !y
:idx-row !ns2
:idx-vec 1
& !m2}
...])
=>
[{:b 2, :a 2, :idx-row 0, :idx-vec 0}
{:b 2, :a 3, :idx-row 0, :idx-vec 1}
{:b 3, :a 4, :idx-row 1, :idx-vec 0}
{:b 3, :a 5, :idx-row 1, :idx-vec 1}]
Unfortunately there are two confusing bits about my solution:
1. I’m using an and
trick to create 2 memory variables !m1 and !m2 because we intend to substitute them twice
2. Using let
to create 2 index variables
hi @U06S1EJPL, Thanks for helping me out. Although I'm happy to see it's possible with meander, I think this might not be a good use case for clarifying the transformation with meander. Especially so, since the real case actually has a vector of size n
in each map with key :a
, instead of size 2.
Cheers
Hi @noprompt! Another case I am dealing and not understanding if I am missing some subtlety is one like below (I shortened the real use for easiness)
((ms/bottom-up
(ms/attempt
(ms/rewrite
{:type (me/pred keyword? *acc) :constraints ?constraints :args *args}
?constraints
{:accumulator *acc :result-binding *result-binding :from ?constraints-ac} ?constraints-ac)))
'({:type :some/keyword,
:constraints [(= item ?item) (= tipo-contrato ?tipo-contrato) (= descontados ?descontados) (= mapa ?mapa)],
:args [something]}))
=> ([(= item ?item) (= tipo-contrato ?tipo-contrato) (= descontados ?descontados) (= mapa ?mapa)])
But if I invert the order of the clauses
((ms/bottom-up
(ms/attempt
(ms/rewrite
{:accumulator *acc :result-binding *result-binding :from ?constraints-ac} ?constraints-ac
{:type (me/pred keyword? *acc) :constraints ?constraints :args *args}
?constraints)))
'({:type :some/keyword,
:constraints [(= item ?item) (= tipo-contrato ?tipo-contrato) (= descontados ?descontados) (= mapa ?mapa)],
:args [something]}))
=> (nil)
What would be the reason for (nil) in the inversion of the order of the clauses?{:accumulator *acc :result-binding *result-binding :from ?constraints-ac}
will match any map even if it doesn't have those keys. You can use (m/some ?constraints-ac)
to make sure the key really exists.
Let the record state that today I tried to write a meander expression to match something with metadata 😛
I’ve done this often enough myself and its come up before… maybe we should add it to the meander.epsilon
?
do you mean automatically try to match metadata? I guess there is an existing feature for sets which needs to be considered:
^{& ?rest-set} #{}
but that seems like a pretty low collision chance! 🙂
Argument for: Seems convenient, Argument against: Metadata is not considered in equality (is that important??? I don’t think so)