Fork me on GitHub
#clojure
<
2021-01-28
>
ujwal dhakal07:01:40

any dockerized helloworld clojure app examples out there?

solf08:01:05

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 dhakal08:01:33

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

noisesmith17:01:00

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)

lread18:01:55

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.

lread22:01:16

Interesting. I just retried my clojure/tools.reader tests above for ClojureScript (on a node REPL) and got the behaviour I would expect. A \n is handled the same as Clojure:

(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 for both read-char and peek-char:
(peek-behaviour "o\rhey")
;; => ([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\n is normalized to \n for both read-char and peek-char and peek peeks appropriately to char after \r\n
(peek-behaviour "o\r\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] 
       [5 :peek nil :read nil])

bronsa11:01:30

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

bronsa15:01:36

thanks! appreciated

lread17:01:21

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).

bronsa18:01:41

amazing, thanks

borkdude18:01:05

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

andy.fingerhut19:01:28

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).

andy.fingerhut19:01:33

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

borkdude19:01:08

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

lread19:01:35

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.

borkdude19:01:16

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

lread19:01:03

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.

borkdude19:01:50

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

lread19:01:19

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

lread19:01:21

Just thought the odd behaviour was worth raising.

borkdude19:01:01

@lee @bronsa can probably give the definitive answer

matheusashton19:01:56

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

matheusashton19:01:26

Is there an idiomatic way of doing this?

p-himik19:01:07

Sounds like the job for reductions, I think.

matheusashton19:01:31

wow that's perfect! Exactly what I wanted

noisesmith19:01:15

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)))

👍 3
noisesmith19:01:36

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

matheusashton20:01:42

nice one too thanks!

kenny22:01:31

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.

dpsutton22:01:05

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

kenny22:01:33

reduce ensures order

dpsutton22:01:52

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

dpsutton22:01:08

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

kenny22:01:20

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

dpsutton22:01:16

ah that's a sorted map

dpsutton22:01:09

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

dpsutton22:01:33

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

kenny22:01:34

Calling reduce-kv is implemented as above, not reduce

dpsutton22:01:51

oh i missed that distinction

kenny22:01:34

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

dpsutton22:01:11

that seems like a good point

dpsutton22:01:18

the reduce and reduce-kv will be quite different

kenny22:01:32

Right. Seems odd, right?

dpsutton22:01:34

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

kenny22:01:08

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

dpsutton22:01:21

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

dpsutton22:01:23

(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))))

dpsutton22:01:42

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

dpsutton22:01:51

although its pretty complicated so maybe i missed it

kenny22:01:39

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

dpsutton22:01:04

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

kenny22:01:47

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?

kenny22:01:24

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]}

kenny22:01:12

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)

kenny22:01:27

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.

kenny22:01:32

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.

ghadi22:01:36

what is m two code blocks ago?

kenny22:01:56

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

lread22:01:16
replied to a thread: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 (-&gt; 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") ;; =&gt; ([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") ;; =&gt; ([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") ;; =&gt; ([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.

Interesting. I just retried my clojure/tools.reader tests above for ClojureScript (on a node REPL) and got the behaviour I would expect. A \n is handled the same as Clojure:

(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 for both read-char and peek-char:
(peek-behaviour "o\rhey")
;; => ([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\n is normalized to \n for both read-char and peek-char and peek peeks appropriately to char after \r\n
(peek-behaviour "o\r\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] 
       [5 :peek nil :read nil])