Fork me on GitHub
#malli
<
2021-11-24
>
respatialized16:11:50

another encode question: how do I handle subsequences that I want to encode into single values? I've got some data like:

(let [data ["some text" "ex1.csv - file 1" "ex2.csv - file 2"]
      expected-result ["some text" {"file 1" "ex1.csv" "file 2" "ex2.csv"}]]
  (m/encode
    [:catn [:txt [:= "some text"]]
      [:subseq [:repeat {:encode/extract {:leave #(apply merge %)}}
                 [:re {:encode/extract {:enter #(let [[id fnum] (clojure.string/split % #"\s-\s")]
                                                           {fnum id})}}
                      #".* - file \d"]]]]
   data
   (mt/transformer {:name :extract}))
 )

;; => ["some text" {"file 1" "ex1.csv"} {"file 2" "ex2.csv"}]
the #(apply merge %) encoder works to merge the maps extracted if the :repeat schema is a top-level schema, but not if it is a schema for a subsequence of a seqex. am I pushing encode too far here? should I be relying on parse to do this kind of grouping?

respatialized21:11:54

thinking about this a bit more, it doesn't seem like this is possible, as different values are being encoded depending on whether the sequex is top-level or a subsequence: top-level:

(let [data ["ex1.csv - file 1" "ex2.csv - file 2"]
      expected-result {"file 1" "ex1.csv" "file 2" "ex2.csv"}]
  (m/encode
     [:repeat {:encode/extract {:leave #(apply merge %)}}
                 [:re {:encode/extract {:enter #(let [[id fnum] (clojure.string/split % #"\s-\s")]
                                                           {fnum id})}}
                      #".* - file \d"]]
   data
   (mt/transformer {:name :extract}))
 )
;; => {"file 1" "ex1.csv", "file 2" "ex2.csv"}
so really the object of encoding is a complete vector, the vector of maps created after each string element gets encoded. whereas with the subsequence, it's not a clearly delineated individual value:
["some text"
#_"start of subsequence in :repeat"  
 {"file 1" "ex1.csv"} {"file 2" "ex2.csv"}
... #_"arbitrary number of additional repeats"
 #_"end of subsequence in :repeat" ]
and thus cannot be passed in as an argument to the function referenced in :encode/extract , even if that function accepts varargs or an input sequence. so I think I need to rely on m/parse to do the grouping I am hoping for here.

Adam Helins18:11:57

Is there some way for having context sensitive transformers? e.g. when transforming a child in a coll, being able to take into account what happened to already transformed children

Adam Helins09:11:05

In other words, is transforming strictly context-free?

ikitommi11:11:19

could you provide an minimalistic example when this would be useful. There was a discussion about this long ago, but a) there was no real-life examples for “why?” and b) context-free made performance optimization much easier. Happy to revisit, but need the a) 🙂

ikitommi11:11:54

there was also a discussion just to implement all applications (validation, transforming) using walk. That was my original idea for Spec too (https://clojure.atlassian.net/browse/CLJ-2251).

ikitommi11:11:17

4 years! time flies 🙂

ikitommi11:11:26

> Created 11 October 2017, 22:22

ikitommi11:11:19

could you provide an minimalistic example when this would be useful. There was a discussion about this long ago, but a) there was no real-life examples for “why?” and b) context-free made performance optimization much easier. Happy to revisit, but need the a) 🙂