Fork me on GitHub
#clojure
<
2021-10-22
>
gabriel12:10:38

Hi, Is it ok to make a lib where some of the namespaces (not :required by others ns) can be loaded only if a given Java lib is on the classpath ? The context of this question is a wrapper around a Java lib, OpenTelemetry, which is separated in 2 artifacts: “API” and “SDK”. The goal is to have lib authors instrument their lib using “API” facade, at almost no runtime costs, and then to have end users include the SDK in production to get actual implementation. So writing a wrapper for this, I shouldn’t need to rely on “SDK”, but there is small areas where I want to offer optional wrapper on things that exist only in the SDK, which shouldn’t trigger a transitive dependency for the clojure lib’s users.

p-himik12:10:18

From what I can tell, it's a pretty common practice for when you need to have such optional functionality that doesn't make sense as a separate package.

gabriel12:10:33

Ok, thank you !

mbertheau16:10:28

Is there a shorter way to write (into {} (map #(vector % (some-function %))) some-seq) or the equivalent (into {} (for [el some-seq] [el (some-function el)]))? In Python it'd be {el: some_function(el) for el in some-seq} and I wonder if there is something of similar syntactical complexity (or rather simplicity) in Clojure. The intermediate vector representation of a key-value-pair seems kind of unwieldy.

emccue16:10:17

I wrote a for-map macro for myself at one point

quoll16:10:34

Not that what you’ve said is necessarily bad, but there are options. For instance:

(zipmap (map some-function some-seq) some-seq)

emccue16:10:51

So that would look like

(for-map [el some-seq]
  [el (some-function el)])

dpsutton16:10:41

(into {} (map (juxt identity f)) the-seq) also, if you pull that into a helper that takes f and the seq the call sites could be quite trim

quoll16:10:34

Ooops, I mixed up key/value (narrow screen):

(zipmap some-seq (map some-function some-seq))

1
emccue16:10:42

There is also a map vals somewhere for simple cases (idk if there is a standard one yet)

quoll16:10:20

Looking at some of the suggestions, it appears that every version here creates a temporary vector (which is extremely common in Clojure, and not a big deal), with the exception of zipmap. Both zipmap and everything else uses transient maps. The only real difference is that zipmap loops through using assoc!, while using into loops through using conj! (which accepts the 2 element vector)

emccue17:10:23

for-map doesn’t need to - it just needs a syntax literal vector - it can translate to zipmap like stuff hypothetically

mbertheau19:10:39

Thanks for the ideas!

kbsant08:10:49

You can use reduce: (reduce #(assoc %1 %2 (some-fn %2)) {} some-seq))

quoll16:10:46

Yes! Though the advantage of using into or zipmap is the transient. So:

(persistent! (reduce #(assoc! %1 %2 (some-fn %2)) (transient {}) some-seq)))

Joshua Suskalo17:10:53

I notice that binding-conveyor-fn is private in clojure.core. Is there a recommended way to perform the same function in cases where a library is providing a different asynchronous execution framework than futures?

Joshua Suskalo17:10:00

Ah, yeah, that should work. Thanks!

👍 1
jumar04:10:27

There was some subtle difference between them that I don’t remember now You can also use #’binding-conveyor-fn