0

In this question (How to return two customSVGSeries from a single function in clojurescript), I learned how to insert the result of a function creating two customSVGSeries into an XYPlot.

Now I want to insert the result of a for calling that same function:

(into [:> rvis/FlexibleXYPlot {...}] 
      (doall (for [[id {:keys [x y texto]}] etiquetas]
               (crear-etiqueta id x y texto))))

Where etiquetas is a map with this form:

{:etiqueta-1 {:x 0, :y 0, :texto ["176.6"]}, :etiqueta-2 {:x 1, :y 2, :texto ["Hidrógeno"]}}

and crear-etiqueta is the function returning two customSGVSeries. The problem is that using the code above, nothing is shown in the plot.

I uploaded a repo with a MWE: https://github.com/lopezsolerluis/annie-test-for-stackoverflow

Edit

I used the excellent idea of Eugene... it works like a charm!

     (into [:> rvis/FlexibleXYPlot {...}] 
            (mapcat (fn [[id {:keys [x y texto]}]]
                       (crear-etiqueta id x y texto))
                    etiquetas))

Luis López
  • 159
  • 8
  • 1
    You don't need `doall` because `into` will realize the result of `for`. If `crear-etiqueta` returns a vector of two items but in the end you need a long flat sequence of items, you have to flatten them somehow. One way is to use the same `for` since it can accept multiple collections: `(for [a xs, b a] ...)`. Another way is to use `mapcat` as a transducer and move `crear-etiqueta` there. – Eugene Pakhomov Mar 16 '22 at 20:06
  • That's great! I would like you have posted it as an answer. :) Anyway, I didn't undestand the first solution (using `for`), and still need to understand the transducer utility. But at least I could have a solution! Thank you very much. – Luis López Mar 16 '22 at 22:14

1 Answers1

1

Expanding on my comment to the question.

Using for with two collections:

(into [:> rvis/FlexibleXYPlot {...}] 
      (for [[id {:keys [x y texto]}] etiquetas
            series (crear-etiqueta id x y texto)]
        series))

for will iterate over eqieuetas and for each item it will destructure it and pass the result into crear-etiqueta, which returns a collection. for then iterates over that collection and assigns the value of each item to series. Then the body is finally evaluated, which just returns the value of series.

Using the mapcat transducer:

(into [:> rvis/FlexibleXYPlot {...}]
      (mapcat (fn [[id {:keys [x y texto]}]]
                (crear-etiqueta id x y texto)))
      etiquetas)

I won't go into the details of how it works - it's all documented here. I definitely recommend reading that reference in full because of immense usefulness of transducers in many contexts.

Eugene Pakhomov
  • 9,309
  • 3
  • 27
  • 53