clojure

New to Clojure? Try the #beginners channel. Official docs: https://clojure.org/ Searchable message archives: https://clojurians-log.clojureverse.org/
ujwal dhakal 2021-01-28T07:58:40.444200Z

any dockerized helloworld clojure app examples out there?

solf 2021-01-28T08:16:05.444300Z

Well, if it's really a hello world you want...

`--> cat << EOF > Dockerfile
FROM clojure:openjdk-13-tools-deps-slim-buster
CMD clojure -M -e '(println "Hello World")'
EOF

`--> docker build -t clj-hello-world .
Sending build context to Docker daemon  18.43kB
Step 1/2 : FROM clojure:openjdk-13-tools-deps-slim-buster
---> cb4db6dd0873
Step 2/2 : CMD clojure -M -e '(println "Hello World")'
---> Running in b54c6b45b466
Removing intermediate container b54c6b45b466
---> c3116a0119a6
Successfully built c3116a0119a6
Successfully tagged clj-hello-world:latest

`--> docker run clj-hello-world
Hello World

ujwal dhakal 2021-01-28T08:47:33.444500Z

thanks so for auto file changes like we do on js i need to use REPL right?

uosl 2021-01-28T12:39:43.445100Z

Yes, but you can also use https://ring-clojure.github.io/ring/ring.middleware.reload.html if you use ring server

2021-01-28T17:39:00.447Z

using clojure in the CMD is like packaging up gcc in your docker, and downloading libs and compiling on startup. clojure is a dep resolution / build tool and should be used during or before packaging, not inside your runtime command (it's a minor issue here, it just means downloading jars every time you spin the container up at worst, but in a real app it's better to resolve deps and package things before putting them into a container)

lread 2021-01-28T18:14:55.458100Z

Hiya folks! I’m working on Windows newline bug in rewrite-clj, and while digging in, I’ve found that clojure.tools.reader push back reader read-char and peek-char seem to treat \r\n differently. To demonstrate, I’ll setup a reader like rewrite-clj does and dump peek and read behavior:

(defn peek-behaviour [s]
  (let [rdr (-> s 
                r/string-push-back-reader
                r/indexing-push-back-reader)]
    (map (fn [ndx]
            [ndx :peek (r/peek-char rdr) :read (r/read-char rdr)])
          (range (count s)))))
A \n is handled as one would expect:
(peek-behaviour "o\nhey")
;; => ([0 :peek \o :read \o]
;;     [1 :peek \newline :read \newline]
;;     [2 :peek \h :read \h]
;;     [3 :peek \e :read \e]
;;     [4 :peek \y :read \y])
A \r is normalized to \n by read-char but not by peek-char:
(peek-behaviour "o\rhey")
;; => ([0 :peek \o :read \o]
;;     [1 :peek \return :read \newline]
;;     [2 :peek \h :read \h]
;;     [3 :peek \e :read \e]
;;     [4 :peek \y :read \y])
And \r\n is normalized to a single \n by read-char but not by peek-char (this is where rewrite-clj gets tripped up, it assumes ndx 2 :peek would be \h)
(peek-behaviour "o\r\nhey")
;; => ([0 :peek \o :read \o]
;;     [1 :peek \return :read \newline]
;;     [2 :peek \newline :read \h]
;;     [3 :peek \e :read \e]
;;     [4 :peek \y :read \y]
;;     [5 :peek nil :read nil])
Is this expected clojure.tools.reader behaviour? I’m sure I can work around this behaviour for rewrite-clj but thought I should ask.

bronsa 2021-01-29T11:30:30.499600Z

can you make a ticket in the tools reader jira? I'll have a look at it when i have some time soon

lread 2021-01-29T15:32:25.007400Z

will do @bronsa!

bronsa 2021-01-29T15:32:36.007600Z

thanks! appreciated

lread 2021-01-29T17:57:21.014100Z

Ok here it is @bronsa: https://clojure.atlassian.net/browse/TRDR-65 (I started fresh and carefully, raising the issue had me fix my ClojureScript examples above, not sure I ended up with chars returned for cljs).

bronsa 2021-01-29T18:40:41.014600Z

amazing, thanks

borkdude 2021-01-28T18:57:05.458900Z

@lee Maybe non-significant difference, but I think rewrite-clj uses clojure.tools.reader.edn under the hood. Probably uses the same functions though.

2021-01-28T19:00:28.461400Z

I do not know the specifics of that issue, but I do know that trying to maintain compatibility with Clojure's reader, maintaining column and line info, handline \n vs \r\n differences, and some corner cases involving look-ahead then unread 1 character used in some cases, can be notoriously confusing to handle in clojure.tools.reader (from personal involvement in examining test cases submitted by others in earlier JIRA issues, and trying to figure out why they occurred).

2021-01-28T19:01:33.461900Z

oh, and contributing to the difficulty is that there can be different 'layering' of JVM IndexedPushbackReader vs. BufferedReader vs. different combinations of those.

borkdude 2021-01-28T19:03:08.462800Z

It seems tools.reader has some normalize? option to normalize \r\n to \n, in read-char and unread-char, but perhaps this normalization isn't needed in peek-char as peek-char is often just used to determine if the next char is some special character and not some whitespacy thing

lread 2021-01-28T19:17:35.466900Z

Thanks @borkdude & @andy.fingerhut! The lack of symmetry on read-char vs peek-char for newlines is a bit surprising at first glance, but maybe there’s a good reason for it that I just don’t know yet.

borkdude 2021-01-28T19:19:01.467900Z

@lee @bronsa can probably give the definitive answer

borkdude 2021-01-28T19:20:16.468Z

@lee So why does rewrite-clj have problems with this?

lread 2021-01-28T19:23:03.468200Z

It is the way it currently parses comments. It is the only element is parses to end of line. If a comment ends in \r\n it gets confused due to the peek-char/read-char mismatch. I can work around current tools.reader behaviour, I’m sure.

borkdude 2021-01-28T19:23:50.468400Z

why doesn't it use read-char until it gets a newline?

lread 2021-01-28T19:25:19.468600Z

I will switch to exactly that. It tries to reuse one of its utility functions to parse to end of line.

lread 2021-01-28T19:26:21.468800Z

Just thought the odd behaviour was worth raising.

matheusashton 2021-01-28T19:41:56.473200Z

Hello guys! I have a collection of commands that I need to proccess and each command causes an update in my "state" so I used a reduce to apply every command using an empty state as first val, but one thing I need is to print every intermediate state and I can't do that with a reduce because I'll only have the last state at the and, also I can't use a map because one command should be applied to the previous state result 😕 and I'm struggling with putting the print inside the function that reduce calls because looks like a bad practice causing a side effect inside the function with business logic

matheusashton 2021-01-28T19:42:26.473900Z

Is there an idiomatic way of doing this?

p-himik 2021-01-28T19:43:07.474300Z

Sounds like the job for reductions, I think.

matheusashton 2021-01-28T19:44:31.474600Z

wow that's perfect! Exactly what I wanted

matheusashton 2021-01-28T19:44:58.474900Z

Thanks!

2021-01-28T19:45:15.475100Z

since you only need the intermediate values for a side effect, also consider a middleware / wrapping pattern -

(defn logged [f]
  (fn [& args]
    (print-args args)
    (apply f args)))

👍 1
2021-01-28T19:45:36.475300Z

then (reduce (logged state-f) init coll)

matheusashton 2021-01-28T20:17:42.475900Z

nice one too thanks!

kenny 2021-01-28T22:06:31.485200Z

I'm curious why reduce-kv for a priority-map calls the reducing function with item as the key and priority as the value (https://github.com/clojure/data.priority-map/blob/master/src/main/clojure/clojure/data/priority_map.clj#L395-L397) instead of the map's key and value. Calling reduce will be passed the map's key and value. I'm assuming it has something to do with this particular data structure's origins, but I cannot find any documentation pointing me to in in the clojure.data.priority-map ns.

dpsutton 2021-01-28T22:18:05.486300Z

my guess would be that's a good way to ensure that you get all of the same priority items at the same time. otherwise you might get a low priority, a high priority, a low priority of the same precedence as the previous one, etc

kenny 2021-01-28T22:18:33.486500Z

reduce ensures order

dpsutton 2021-01-28T22:18:52.486700Z

priority->set-of-items is a map i think?

dpsutton 2021-01-28T22:19:08.486900Z

if its reducing over an unordered thing then i don't see how this implementation does

kenny 2021-01-28T22:19:20.487100Z

I mean calling reduce on a priority map, not that internal map.

dpsutton 2021-01-28T22:20:16.487300Z

ah that's a sorted map

dpsutton 2021-01-28T22:21:09.487500Z

i'm not following. calling reduce on the priority map is implemented as that above, calling reduce on the sorted map priority->set-of-items

dpsutton 2021-01-28T22:21:33.487700Z

but i guess its a good decision that when reducing you're given every item of equal priority at the same time

kenny 2021-01-28T22:21:34.487900Z

Calling reduce-kv is implemented as above, not reduce

dpsutton 2021-01-28T22:21:51.488200Z

oh i missed that distinction

kenny 2021-01-28T22:22:34.488400Z

Since PersistentPriorityMap doesn't implement IReduceInit, it must be calling coll-reduce

dpsutton 2021-01-28T22:23:11.488600Z

that seems like a good point

dpsutton 2021-01-28T22:23:18.488800Z

the reduce and reduce-kv will be quite different

kenny 2021-01-28T22:23:32.489Z

Right. Seems odd, right?

dpsutton 2021-01-28T22:23:58.489200Z

yeah

dpsutton 2021-01-28T22:24:34.489400Z

certainly when there's a custom reduce-kv way implemented

kenny 2021-01-28T22:25:08.489600Z

Yep. Makes me think it was intentional, which led me to my guess of having to do with priority map CS origins or something

dpsutton 2021-01-28T22:26:21.489800Z

i see in the reducers ns there's some stuff where the reduce-kv is used if present

dpsutton 2021-01-28T22:26:23.490Z

(defn reduce
  "Like core/reduce except:
     When init is not provided, (f) is used.
     Maps are reduced with reduce-kv"
  ([f coll] (reduce f (f) coll))
  ([f init coll]
     (if (instance? java.util.Map coll)
       (clojure.core.protocols/kv-reduce coll f init)
       (clojure.core.protocols/coll-reduce coll f init))))

dpsutton 2021-01-28T22:26:42.490200Z

but i don't remember seeing anything like that in the reduce pathway

dpsutton 2021-01-28T22:26:51.490400Z

although its pretty complicated so maybe i missed it

kenny 2021-01-28T22:27:39.490600Z

Not sure I'm following what you're looking for.

dpsutton 2021-01-28T22:29:04.490800Z

i was wondering if there was some code pathway that checked if it wasn't ireduceinit but it was IKVReduce that maybe it would use that pathway

kenny 2021-01-28T22:33:47.491400Z

Main question is why the author added a custom reduce-kv impl that does not pass what I'd expect for the value. Is it intentional? Bug?

kenny 2021-01-28T22:37:24.491600Z

e.g.,

(reduce-kv
    (fn [acc k v]
      (assoc acc k v))
    {} m)
=> {:b 1, :a 2}
(reduce
    (fn [acc [k v]]
      (assoc acc k v))
    {} m)
=> {:b [1 :bananas], :a [2 :apples]}

kenny 2021-01-28T22:39:12.491800Z

It seems like the correct implementation of reduce-kv would be

(reduce-kv (fn [a priority items]
             (reduce (fn [a item] (f a item (item->priority item))) a items))
  init priority->set-of-items)

kenny 2021-01-28T22:41:27.492Z

This part of the readme describes approximately how reduce-kv is working > In addition to supporting all the functions a sorted map supports, a priority map can also be thought of as a queue of [item priority] pairs. To support usage as a versatile priority queue, priority maps also support conj/peek/pop operations.

kenny 2021-01-28T22:42:32.492200Z

So is it expected that reduce-kv on a priority map should work like that queue? IMO, that seems incorrect -- use the seq interface or queue fns.

ghadi 2021-01-28T22:46:36.493400Z

what is m two code blocks ago?

kenny 2021-01-28T22:46:56.493600Z

(def m
    (clojure.data.priority-map/priority-map-keyfn-by first compare
      :a [2 :apples] :b [1 :bananas]))