Fork me on GitHub
#clojure
<
2023-05-16
>
agorgl06:05:29

How can I, in a vector of maps, remove all but the last items that are duplicate based on the key? E.g. Given the input:

[{:id "remote",
  :desc "Manage remote host",
  :long-opt "--remote",
  :short-opt "-r",
  :required "HOST"}
 {:id "version",
  :desc "Show program version",
  :long-opt "--version",
  :short-opt "-v"}
 {:id "help",
  :desc "Show network help summary",
  :long-opt "--help",
  :short-opt "-h"}
 {:id "active",
  :desc "Pick only active networks",
  :long-opt "--active",
  :short-opt "-a"}
 {:id "help",
  :desc "Show network create help summary",
  :long-opt "--help",
  :short-opt "-h"}]
I need to discard the first (duplicate) map with :id "help" and keep only the last one:
[{:id "remote",
  :desc "Manage remote host",
  :long-opt "--remote",
  :short-opt "-r",
  :required "HOST"}
 {:id "version",
  :desc "Show program version",
  :long-opt "--version",
  :short-opt "-v"}
 {:id "active",
  :desc "Pick only active networks",
  :long-opt "--active",
  :short-opt "-a"}
 {:id "help",
  :desc "Show network create help summary",
  :long-opt "--help",
  :short-opt "-h"}]

agorgl06:05:15

Thanks! I did a (->> coll (reverse) (distinct-by :id) (reverse)) and that did the trick

p-himik08:05:16

Note that there's also rseq which should be better for longer collections since it's created in constant time. The downside is that not all collection types support it (vectors do though).

Colin17:05:51

If you didn’t care about order you could (->> v (map #(vector (:id %) %)) (into {}) vals)

Casey07:05:10

I need to have a few java files in my clojure project. They are relatively small and I'd rather not make a separate repo/library just for them. I've followed the tools.build instructions for compiling them and getting them in my uberjar, however I'm having trouble using them during dev at the REPL. I have a :deps/prep-lib in my deps.edn (which feels strange, since my project isn't a library, and calling clj -X:deps prep doesn't produce any output. And of course when I try to load the classes in my REPL I get ClassNotFoundException.

Casey07:05:29

snippet from my deps.edn:

:paths ["resources" "src/clj" "src/java"]

 :deps/prep-lib {:alias  :build
                 :fn     compile
                 :ensure "target/classes"}
snippet from build.clj
(defn compile [_]
  (b/javac {:src-dirs ["src/java"]
            :class-dir class-dir
            :basis basis
            :javac-opts ["-source" "17" "-target" "17"]}))

(defn uberjar "build the uberjar" [_]
  (let [opts (uber-opts {})]
    (clean nil)
    (compile nil)
      (b/write-pom {:class-dir class-dir
                    :lib lib
                    :version version
                    :basis basis
                    :src-dirs ["src"]})
    (b/copy-dir {:src-dirs ["src" "resources"]
                 :target-dir class-dir})
    (b/compile-clj {:basis basis
                    :src-dirs ["src"]
                    :class-dir class-dir})
    (b/uber opts)))

Casey07:05:25

Aha! I've figured it out. I just needed to get the compiled classes on the classpath.

Casey07:05:16

deps.edn becomes simply

:paths ["resources" "src/clj" "src/java-classes"]
and I made a separate compile fn for putting the classes in src/java-classes
(defn compile-dev [_]
  (b/javac {:src-dirs ["src/java"]
            :class-dir "src/java-classes"
            :basis basis
            :javac-opts ["-source" "17" "-target" "17"]})) 

vemv13:05:22

Looks good, simply keep in mind a .class file is not a source file. target/dev/classes would look a litte more standard

vemv13:05:02

By any chance anyone is gathering JMX metrics in GCP Cloud Run through google's built-in offering (i.e. its Ops Agent)? I got stuck setting it up, could persevere, although I suspect my approach could be simpler.

👀 1
souenzzo20:05:22

Does this function exists in clojure.core or in any other library?

(defn pooled-pmap
  [^ExecutorService pool f vs]
  (let [futures (for [v vs]
                  (.submit pool ^Callable (partial f v)))]
    ;; be sure to submit all before starting deref
    (doall futures)
    ;; lazily return all derefered futures
    (map deref futures)))
I think that agents is kind of it. maybe it could be simpler if i use agents?!

kwladyka20:05:48

I don’t know what is your goal, so hard to answer if agent fit into your needs or not

kwladyka20:05:44

but if you want to do parallel then use async instead of any above

kwladyka20:05:07

this is more about managing state, not about performance

kwladyka20:05:20

but async is for performance

kwladyka20:05:29

at least how I see this

souenzzo20:05:33

I have n operations to do I'd like to realize them with m active operations per time. Eventually, get the result. My goal is just realize n operations, with m active per time • not an async thing • not an performance thing

kwladyka20:05:51

pipeline or pipeline-blocking sounds like async for me. You want to control number of threads (`m` active per time) and process n items. With pipeline you set m and input data in 1 line.

(async/pipeline-blocking 3 csv-chan (map url->csv) (async/to-chan!! urls-to-sync))

souenzzo20:05:32

I think that pipelines may work. let me try

igrishaev06:05:38

There is no such a built-in function but you can implement it this way:

(defmacro with-pool [[bind threads] & body]
  `(let [~bind (Executors/newFixedThreadPool ~threads)]
     (try
       ~@body
       (finally
         (.shutdown ~bind)))))

;; then

(with-pool [pool 8]

  (let [futures
        (new ArrayList)]

    (doseq [chunk chunks]

      (let [fut
            (.submit pool
                     ^Callable
                     (fn []
                       (bla-bla)))]

        (.add futures fut)))

    (reduce + (map deref futures))))

hiredman06:05:50

You can't actually type hint function literals like that

igrishaev06:05:54

hm, this code works, I took it from a real project. Without the ^Callable hint, there is a reflection warning.

hiredman06:05:31

It will work but still be reflective if you are tagging the function literal

hiredman06:05:54

But it will not be if tag a symbol that a function is bound to

hiredman06:05:28

My guess would be the project you took it from doesn't pass a function literal there

igrishaev06:05:23

well, I copied a fragment were we pass an inline function. But the code might be easily refactored such that it accepts a function

hiredman06:05:23

Might have been a but that got fixed at some point

vemv07:05:42

> I think that agents is kind of it. maybe it could be simpler if i use agents? Agents have send-via to specify a custom pool, probably it maps well to your q

igrishaev08:05:15

yep, just an example:

(with-pool [pool 4]
  (let [a (agent [])]
    (doseq [x [1 2 3 4]]
      (send-via pool a conj x))
    (await a)
    @a))
where the with-pool macro comes from the previous code snippet

Eugen21:05:28

hi, any idea how I can get the type of the array item ? I might have only an empty array (i think).

(type (make-array java.util.Map$Entry 0)) 
I get [Ljava.util.Map$Entry; I would like to get map$Entry

seancorfield21:05:00

[L...; is Java's way of saying "array of ..."

seancorfield21:05:18

(and you are asking for the type of the array, not an element within it)

p-himik21:05:02

(.arrayType (.getClass (int-array 0)))
=> [[I
(.componentType (.getClass (int-array 0)))
=> int
(.componentType (.getClass (make-array java.util.Map$Entry 0)))
=> java.util.Map$Entry

😮 3
Eugen22:05:25

works like a charm! thanks