Fork me on GitHub
#meander
<
2023-05-31
>
zane19:05:50

The https://cljdoc.org/d/meander/epsilon/0.0.650 in the README appears to be broken?

lread13:06:41

Hey @zane, I'll take a peek and see what problem cljdoc is having here.

lread14:06:09

The https://repo.clojars.org/meander/epsilon/0.0.650/epsilon-0.0.650.pom does not point back to meander sources on GitHub.

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="" xmlns:xsi="" xsi:schemaLocation=" ">
  <modelVersion>4.0.0</modelVersion>
  <packaging>jar</packaging>
  <groupId>meander</groupId>
  <artifactId>epsilon</artifactId>
  <version>0.0.650</version>
  <name>epsilon</name>
  <dependencies>
    <dependency>
      <groupId>org.clojure</groupId>
      <artifactId>clojure</artifactId>
      <version>1.10.3</version>
    </dependency>
  </dependencies>
  <build>
    <sourceDirectory>src</sourceDirectory>
  </build>
  <repositories>
    <repository>
      <id>clojars</id>
      <url></url>
    </repository>
  </repositories>
</project>

lread14:06:19

Cljdoc https://github.com/cljdoc/cljdoc/blob/master/doc/userguide/for-library-authors.adoc#git-sources`<scm>`https://github.com/cljdoc/cljdoc/blob/master/doc/userguide/for-library-authors.adoc#git-sources. Older versions of meander published to clojars do have some <scm> info so, the build process probably changed. And meander does have a doc/cljdoc.edn to there has been historical interest in cljdoc.

zane14:06:23

Er, rather the link isn’t broken, but the page it takes you to is.

zane14:06:35

Thanks for looking into it, @UE21H2HHD!

lread14:06:25

Oh @zane, I think I maybe misunderstood, I thought you were noting that the articles did not import on cljdoc, and that's what I looked into. simple_smile

zane14:06:05

That is what I noticed! Sorry for the confusion.

lread14:06:14

Oh good. Same page then!

zane14:06:51

I was just trying to clarify what was probably already clear from the screenshot: That the link successfully takes you to a webpage, but that the webpage has problems.

👍 2
lread14:06:20

Should we raise an issue on meander repo?

zane14:06:45

Sounds good!

cch120:05:32

I’m struggling with meander’s documentation for what (to me) seems to be a simple transformation. I want to transform nested repeated content along with the containing content. I can’t figure it out. Here’s an example:

{:a [{:b 1 :x 12} {:b 2 :y 13}]}
needs to become:
{:A [{:B 1 :x 12} {:B 2 :y 13}]}
It’s the changes to the N contained maps that confounds me. I can do it with a “manual” mapping of meander/match over the value at the :a key, but that seems to break the promise of meander’s declarative approach. Thanks in advance, and my apologies if I’ve missed something in the docs. Memory variables seem like a crucial ingredient, but I can’t see a way to “unify” the elements of each map “positionally” in the output expression to preserve the arity of the input value.

Richie13:06:45

You want to rewrite everything in the top level and also everything one level down? I might just thread through two rewrites.

cch114:06:45

Yes, that’s correct. Can you explain what you mean by “thread through two rewrites?” The cleanest method I can come up with involves mapping over the repeated key’s value with a secondary meander/match call. But that just seems wrong. Here’s the rough shape:

(meander/match input
	       {:a [!nested ...]}
	       {:A (mapv #(meander/match %
					 {:b ?b :x ?x :y ?y}
					 {:B ?b :x ?x :y ?y})))
(the :x and :y keys are not particularly relevant to this problem and their nil values in the result doesn’t match exactly the example I gave above -ignore it)

Richie15:06:25

Hmm. What I had in mind didn't work when I actually tried to write code. I was thinking thread-first -> through m/rewrite for :a to :A and then again m/rewrite to turn {:A [{:b ... into {:A [{:B ...

Richie15:06:39

This probably isn't what you want but I still don't understand what you want.

(m/rewrite {:a [{:b 1 :x 3}
                {:b 2 :y 4}]}
  {:a [!a ...] & ?rest}
  {:A [(m/cata !a) ...] & ?rest}
  {:b ?b & ?rest}
  {:B ?b & ?rest})

Richie15:06:41

gives {:A [{:x 3, :B 1} {:y 4, :B 2}]}

Richie15:06:48

m/cata recurses on each thing. If there's another :a there then it'll get matched. that's probably not what you want.

Jimmy Miller15:06:00

Is this the kind of thing you are looking for?

(def input {:a [{:b 1 :x 12} {:b 2 :y 13}]})

(m/rewrite input
  {:a [{:b !bs & !xs} ...]}
  {:A [{:B !bs & !xs} ...]})

;; =>
;; {:A [{:x 12, :B 1} {:y 13, :B 2}]}

cch115:06:34

In words, I want to transform a map containing a sequence of maps at some key. I see how to transform a map with a sequence at some key, but if the sequence is composed of maps then I see no way to modify the child maps without a second invocation of meander. It seems weird that nested data structures can’t be “described” sufficiently to allow this. Again, here is the shape of the input:

{:a [{:b 1} {:b 2}]}
The desired output requires transformation of the outer map and the inner maps. So something like this:
{:A [{:B 1} {:B 2}]}
The keys at each level are arbitrary and could be duplicated such that nesting context would be essential, but my data doesn’t have that twist.

cch115:06:16

@U5K8NTHEZ, I need to study your solution -it looks very close to what I need.

cch116:06:57

Unfortunately, I think the problem with that solution is that it treats the subsequence as a memorization (= memory variable) and AFAICT there is no means to correlate memory variables. A slightly extended example shows how that approach will come up short:

{:a [{:b 1 :c 3} {:b 2 :c 4}]}
the desired output requires that the inner maps remain correlated entities:
{:A [{:B 1 :C 2} {:B 2 :C 4}]}

cch116:06:38

With memory variables, I don’t think it is possible to retain the correlation of 1 and 3 in the first inner map (and similarly for 2 and 4 in the second inner map). My expectations might be unreasonable: I was expecting equivalent transformation power on nested repeated data as on the top-level data. Perhaps invoking meander twice is the best option.

Richie17:06:22

(m/rewrite {:a [{:b 1 :c 3} {:b 2 :c 4}]}
  {:a [{:b !b :c !c & !xs} ..!n] & ?rest}
  {:A [{:B !b :C !c & !xs} ..!n] & ?rest})
;; {:A [{:B 1, :C 3} {:B 2, :C 4}]}

Jimmy Miller17:06:05

I'm confused on the output.

{:b 1 :c 3}
;; turns into 
{:B 1 :C 2}
Was that a typo?

Jimmy Miller17:06:22

Assuming it is a typo

(m/rewrite input
  {:a [{:b !bs :c !cs & !xs} ...]}
  {:A [{:B !bs :C !cs & !xs} ...]})
Seems to work on that input

cch117:06:49

Yep, it was a typo.

Jimmy Miller17:06:40

So yeah. That seems to work. There are ways to correlate memory variables more specifically but I don’t see the need for that here. So I must be missing something.

cch117:06:50

So that ^ shows that the memory variables are being “consumed” in parallel and maintain the correlation of the map entities.

cch117:06:05

Not at all obvious, but nice.

Jimmy Miller17:06:39

Yeah you can do some fancier things with different repeat operators. But in general they do one value for each repeat. So for the same length things they should be fine.

thanks 2
cch115:06:15

@U5K8NTHEZ and @UPD88PGNT, thanks for your help with this. I’ve got additional requirement that I fear may break the solutions you have proposed… I need each of the subordinate output maps to include the index of the subordinate input maps. So using @UPD88PGNT’s example from above:

(m/rewrite {:a [{:b 1 :c 3} {:b 2 :c 4}]}
  {:a [{:b !b :c !c & !xs} ..!n] & ?rest}
  {:A [{:B !b :C !c & !xs} ..!n] & ?rest})
;; {:A [{:B 1, :C 3 :index 1} {:B 2, :C 4 :index 2}]}
Note the addition of the :index key in the desired output. Is this possible? Similarly to how the keys and vals functions in Clojure core commit to returning the keys and values in the same order, I’m wondering if your collective opinion is that the “correlation” of the memory variables is intentional (by the authors of meander) or if it is “luck” -I’m hesitant to invest a lot in this approach without some confidence that it is intentional.

Jimmy Miller16:06:33

Not at my computer. I’ll have to think about index. But I can confirm for sure that the “correlation” isn’t accidental. The way memory variables work is just conceptually push and pop into a vector.

Jimmy Miller21:06:57

For index, I am sure there is some other way. But this was what I first came up with for doing it.

(m/rewrite {:a (map-indexed vector [{:b 1 :c 3} {:b 2 :c 4}])}
  {:a ([!index {:b !b :c !c & !xs}] ...) & ?rest}
  {:A [{:B !b :C !c :index (m/app inc !index) & !xs} ...] & ?rest})
Maybe not the most elegant approach ever. But as far as I know we don't have any way to get the index of where you are in a vector. Maybe some cata magic? But personally, I think it is totally fine to do some preprocessing. So ultimately, I'd just do something like
defn add-index [coll]
  (into []
        (map-indexed
         (fn [i x]
           (assoc x :index (inc i))))
        coll))


(m/rewrite {:a (add-index [{:b 1 :c 3} {:b 2 :c 4}])}
  {:a [{:b !b :c !c & !xs} ...] & ?rest}
  {:A [{:B !b :C !c & !xs} ...] & ?rest})

cch123:06:27

THanks. I agree: some pre- and post- processing to add content is OK.