clojure

conao3 2026-01-12T09:10:14.854439Z

(conj {:a 1 :b 2 :c 3}
      {:a 4 :d 5})
;;=> {:a 4, :b 2, :c 3, :d 5}

(merge {:a 1 :b 2 :c 3}
       {:a 4 :d 5})
;;=> {:a 4, :b 2, :c 3, :d 5}
I found conj can 'merge' 2 maps. Then, what is the purpose of the merge function?

Dave Liepmann 2026-01-12T09:26:26.983609Z

The implementation of merge is enlightening to this point. Compare for instance their behavior handling an absence of arguments or nil.

conao3 2026-01-12T09:30:00.154389Z

(conj {:a 1 :b 2 :c 3} nil)
;;=> {:a 1, :b 2, :c 3}

(merge {:a 1 :b 2 :c 3} nil)
;;=> {:a 1, :b 2, :c 3}

(conj nil nil)
;;=> (nil)

(merge nil nil)
;;=> nil
This shows the difference between nil and nil. I learned for the first time that you can concatenate to nil. Does this mean that merge behaves intuitively correctly, particularly with maps?

conao3 2026-01-12T09:31:46.462779Z

In conj, nil seems to be treated equivalently to an empty list (skipping the lesson that nil isn't actually an empty list). 🀯

Dave Liepmann 2026-01-12T09:32:24.425369Z

Basically yeah. See also e.g. (conj) or (conj nil {}). Multipurpose tool versus specialized affordances.

conao3 2026-01-12T09:34:35.749669Z

okey, thanks!

p-himik 2026-01-12T09:35:23.242199Z

merge is also much more clear when you have stuff like (merge a x). (conj a x) doesn't tell as much.

msolli 2026-01-12T10:01:42.693869Z

(conj nil nil) - this is an example nil punning in Clojure: https://ericnormand.me/article/nil-punning

πŸ™Œ 1
Dave Liepmann 2026-01-15T09:07:17.344749Z

Not just printing: public abstract class AMapEntry extends APersistentVector

2026-01-14T20:44:37.770919Z

(ins)user=> (conj {:a 0} [:b 1])
{:a 0, :b 1}
(ins)user=> (merge {:a 0} [:b 1])
{:a 0, :b 1}
these both work, but I'd argue that only the first one is idiomatic

2026-01-14T20:47:27.455479Z

(it's common to represent a map entry as a vector literal, because that's also how they natively print)

(ins)user=> (first {:a 0})
[:a 0]
(ins)user=> (type *1)
clojure.lang.MapEntry
(ins)user=> (vector? (first {:a 0}))
true

p-himik 2026-01-14T21:36:51.078629Z

Huh, I'm surprised the second doesn't result in {:a 0, 0 :b, 1 1}.

ray 2026-01-12T16:59:13.454149Z

I want to perform side-effects like one would with doseq but I'd rather use eduction as it is more efficient. I've had some pearl clutching at this code:

(reduce (fn [_ [k v]]
              (side-effect-fn k v))
            [] (eduction coll))
Assume coll is a big collection that comes from a database and has a function pipeline applied. This works well but, since I would like to retain my place in polite society πŸ˜…, is there a better option that retains the efficiency / single pass effect that eduction brings? Thanks in advance!

βœ… 1
ray 2026-01-12T17:00:59.711849Z

Yes, I'm looking forward to my own 🀦🏻

dpsutton 2026-01-12T17:01:53.230439Z

i think run! is exactly this

😍 1
βž• 1
πŸ™πŸΌ 1
ray 2026-01-12T17:05:28.656499Z

You got me! 🀦🏻

dpsutton 2026-01-12T17:06:39.813109Z

and one thing i’ve seen is if coll is essentially cursor based results make sure you don’t risk a timeout on a connection held open

ray 2026-01-12T17:07:13.184129Z

thanks, it's all good on that front

πŸ‘ 1
dpsutton 2026-01-12T17:07:33.179239Z

(but i’m a big fan of this pattern, but that’s the one thing that can get annoying when it runs for > 5 min in prod and it dies with a β€œThis resultset is closed” error

ray 2026-01-12T17:13:30.057759Z

Yeah I'm using it on a local RocksDB on a Kafka partition. We get passed an Iterable that we can safely access like this:

with-open [iter (.prefixScan store key-prefix (StringSerializer.))]
but if the processing window blows up (analogous to your connection timeout example), we have bigger problems!

πŸ‘ 1
ray 2026-01-12T17:14:20.169439Z

thanks for the tidy up tip and I can rejoin polite society once more πŸ™πŸΌ

dpsutton 2026-01-12T17:14:27.729199Z

you never left πŸ™‚

πŸ˜… 1
Alex Miller (Clojure team) 2026-01-12T17:15:58.501209Z

you might be interested in this idea too https://ask.clojure.org/index.php/13153/could-gain-another-arity-cover-common-case-feeding-eduction

πŸ‘€ 1
3
phronmophobic 2026-01-12T17:30:56.712339Z

run! is just a wrapper around reduce. Instead of reduce+`eduction`, you can use transduce.

ray 2026-01-12T18:18:55.656989Z

In this case, run! is good for indicating side effects ... I'm explicitly not returning anything

πŸ‘ 1
slipset 2026-01-19T09:48:32.798399Z

reduce-kav would be nicer?

neumann 2026-01-17T15:53:40.749569Z

For those interested in the feature @alexmiller mentioned, please do upvote it in Ask Clojure. More votes = higher priority, at least for anything viable.

1
βœ… 1