Fork me on GitHub
#beginners
<
2018-01-27
>
SoV405:01:31

uh. i think electron is totally overkill for everything, but that's just me... it is an incredibly convenient way to go from webpage to desktop application. curious to hear what others would recommend.

jgh05:01:42

i like sublime. I tried atom recently with the integrated repl plugin someone did but i found sublime + terminal was a smoother experience, e.g. atom doesnt have a repl history and the navigation was more like using a text editor than repl.

jgh05:01:12

i know some people dont like sublime because it’s nagware but honestly the way i see it is i’m spending 8 hours a day on it and making a living using it, I can spring the $80.

gklijs12:01:27

I’m able to generate java classes from clojure using leiningen, and the classes end up on the classpath when I use the jar in another project. But I can’t import them them properly. Anybody has an idea how to solve that?

eMko12:01:01

Creating jar using lein jar and importing into another project worked for me (Clojure and other used libs needs to be on classpath). Another solution is to use lein install which installs it into local mvn repo. You can then pull it as maven dependency with transitive dependencies resolved.

eMko12:01:15

What exactly is your problem? The classes which you want to use from Java needs to be AOTed, if you want them to have static methods you need to explicitly mark them in :gen-class macro.

gklijs12:01:14

The problem is that even though the java files get correctly generated with lein modules install, and the java classes end up on the classpath in the other modules, I can’t import them like other java classes.

gklijs12:01:44

Somehow, they are picked up now, maybe because it was a snapshot dependency.

gilmar14:01:23

Hello guys… I would like know as you create serializer to validate payload in endpoint using clojure with compojure for example.

chris_johnson20:01:33

@linux.soares Do you mean just “what’s a good way to validate inputs in Compojure” or have I misunderstood your question?

gilmar20:01:22

Yes. For example, I need validate payload received in a POST. Example:

POST -> {"name": "Gilmar", "last_name": "Soares", age: 15}

Valid payload: {"name": "Gilmar", "last_name": "Soares", age: "15"}
In payload the difference is a field age is a string not int

chris_johnson20:01:53

I would look at spec for sure as a way to define what the shape of a valid payload is and assert conformance to that spec as one of your first handlers in the route

chris_johnson20:01:25

throw whichever 4xx status code is “malformed input” at your client if validation fails, optionally with some kind of helpful message. 🙂

chris_johnson20:01:53

Here’s the really exhaustive docs for what spec is and why it is that way and how to use it in general: https://clojure.org/about/spec

chris_johnson20:01:29

aaaand a compojure-api wiki page that seems to imply already-existing batteries-included support for either (presumably Plumatic) schema or spec by setting a value for :coercion on your context and then specifying validations on your query params

tdantas21:01:40

good night guys ( at least on UTC+1 timezone ) Need one hand to think properly in functional/clojure way: I have one producer the will publish data every X seconds to consumers. The consumers are going to perform some operations based on the data they received and “return” back to the producer the computed value. The producer will receive the computed values, append into internal list and send back to every consumers on next scheduler tick If I had to implement using Java , I would create a shared state and synchronize the access/computation. But I’m trying to do using clojure and would love not to use the ref types/locks primitives. what I thought was to use channels. My solution ( not working as expected ) was: disclaimer: OOP is my background, would love to solve using idiomatic clojure I’ve created one producer with two channels that would be passed into every consumer (input channel/output channel) - the input channel: I’m using tap/mult to dispatch the same messages to every consumer ( cool working great ) - the output channel: response back from consumers that must be saved on producer to be sent next tick

(defn every [seconds callback]
  (chime-at
    (rest
      (periodic-seq
        (t/now) (t/seconds seconds))) (fn [t]
                                        (callback))))

(defprotocol Lifecycle
  (start [this]))

(defrecord Consumer [id producer->consumer-channel consumer->producer-channel]
  Lifecycle

  (start [this]
    (go-loop []
        (when-let [v (<! producer->consumer-channel)]
            (println (str "Consumer[" id "] received value: " v "\n"))
            (>! consumer->producer-channel (rand-int 3000))
            (recur)))))


(defn start-consumers [n-consumers multiplexer consumer->producer-channel]
  (doall
    (map (fn [cid]
         (let [channel (chan (sliding-buffer 1))]
           (tap multiplexer channel)
           (start (Consumer. cid channel consumer->producer-channel))))
              (range 0 n-consumers))))


(defrecord Producer [frequency n-consumers]
  Lifecycle

  (start [producer]
    (let [consumer->producer-channel (chan (sliding-buffer 1))
          producer->consumer-channel (chan)
          multiplexer (mult producer->consumer-channel)]

      (start-consumers n-consumers multiplexer consumer->producer-channel)

      (every frequency #(go (>! producer->consumer-channel (rand-int 1000)))))))
(start (Producer. 1 2)); every 1 second will send message for 2 consumers what I would like to do ,(I’m not being able ), is on second tick the consumers receive all data that was sent on previous tick and so on ...

tdantas22:01:02

basically , in OOP the producer will update internal state and the scheduler will read the internal state every tick

tdantas22:01:55

my solution was using atom

(defrecord Producer [frequency n-consumers]
  Lifecycle

  (start [producer]
    (let [consumer->producer-channel (chan (sliding-buffer 1))
          producer->consumer-channel (chan)
          multiplexer (mult producer->consumer-channel)
          state (atom [])] ; <----------------------------------------------------------- mutable state

      (start-consumers n-consumers multiplexer consumer->producer-channel)

      (go-loop []                                  ;<------------------------------------------------ waiting for consumers response and append into state
        (swap! state conj (<! consumer->producer-channel))
        (recur))

      (every frequency #(go (>! producer->consumer-channel
                                {:state @state   ;<---------------------------------------------------- deref the shared state and passing it to consumers
                                 :value (rand-int 1000) }))))))
I felt so dirty ! I looks like OO

tdantas22:01:11

pretty sure there is better way to do this

noisesmith22:01:29

you can typically replace atom+channel with an agent - an agent has an implicit queue attached to it and represents a concurrency safe mutable state that you can dereference

tdantas22:01:43

my main concern basically is design

tdantas22:01:50

how to design the code using clojure properly

noisesmith22:01:28

right, using channels and an atom together is more complex than using an agent directly - in particular you have a loop of async code that exists just to conj things

tdantas22:01:17

> in particular you have a loop of async code that exists just to conj things yep