Clojurians
#clojure-italy
<
2017-08-09
>

This page is not created by, affiliated with, or supported by Slack Technologies, Inc.

reborg06:08:20

ah ah bellissimi :slightly_smiling_face:

mdallastella12:08:04

Domandaccia: so che esistono repeat e repatedly ma è tanto brutto usare un reduce su un range?

mdallastella12:08:59

Mi spiego meglio: leggo da un socket, il primo byte che mi arriva mi dice quanti elementi devo deserializzare dopo

mdallastella12:08:11

mettiamo che ho 3 Integer da deserializzare: [3 0 0 0 1 0 0 0 2 0 0 0 3]

mdallastella13:08:22

attualmente uso appunto un reduce

mdallastella13:08:40

(datemi un attimo e vi fornisco un esempio)

mdallastella13:08:33

(def b 
  (-> [3 0 0 0 1 0 0 0 2 0 0 0 3]
        byte-array
        java.io.ByteArrayInputStream.
        java.io.DataInputStream.))

(let [size (.readByte b)]
                 (reduce
                  (fn [acc _]
                    (conj acc (.readInt b)))
                  []
                  (range size)))

mdallastella13:08:46

scusate l'indentazione

mdallastella13:08:34

l'alternativa sarebbe:

(repeatedly (int (.readByte b)) #(.readInt b))

mdallastella13:08:20

sicuramente più carina ma non so...

richiardiandrea13:08:25

@mdallastella sceglierei quella che e' piu' leggibile ma qui c'e' un'altra differenza: repeatedly ritorna una lazy seq e quindi ha un comportamento assai diverso da reduce

mdallastella13:08:57

la documentazione di repeatedly dice che consente side-effects

richiardiandrea13:08:55

si, non dico di no..la mia osservazione e' diversa...volevo dire che dipende anche da come hai impostato il resto del codice e come vuoi effettuare la read...lazy or non lazy

richiardiandrea13:08:28

silly example:

boot.user=> (def t1 (take 10 (repeatedly #(println "tst"))))
#'boot.user/t1
boot.user=> t1
tst
tst
tst
tst
tst
tst
tst
tst
tst
tst
(nil nil nil nil nil nil nil nil nil nil)

richiardiandrea13:08:07

quindi la read la faresti lazy (il che pero' vuol dire che se nel frattempo ti chiudono il reader l'`InputStream` sei fregato)

richiardiandrea13:08:04

io su I/O ci vado sempre non-lazy

mdallastella13:08:20

@richiardiandrea quindi meglio il reduce

reborg20:08:42

Mi scusassero, arrivo tardi sul thread. Lazy VS non-lazy dipende da come comunicano client-server. Se i chunk si scambiano una volta ogni tanto, allora puoi aprire lo stream sul socket, leggere e chiudere (qui sopra manca (.close b)). Se i chunk sono continui, allora ti conviene tenere aperto e creare una lazy-seq dei chunk in arrivo. La tua app diventa reactive a quel punto.

reborg23:08:11

(defn chunks [b]
  (lazy-seq
    (cons
      (let [n (.read b)]
        (when (pos? n)
          (mapv (fn [_] (.readInt b)) (range n))))
      (chunks b))))

(def socket
  (-> [3 0 0 0 1 0 0 0 2 0 0 0 3] 
      byte-array 
      java.io.ByteArrayInputStream. 
      java.io.DataInputStream.))

(with-open [b socket] 
  (take-while seq (chunks b)))