Fork me on GitHub
#clojure
<
2017-05-27
>
lilactown01:05:29

i'm researching server-side development + clojure. I'm currently looking at pedestal and luminus. does anyone know of some good resources to break out the differences between them, and other libs/frameworks?

dragoncube03:05:32

are agents safe choice for new development? are they still embraced by community or cognitect?

john03:05:52

They're only recommended for specific classes of problems, but cognitect still supports them, as well as all of the other reference types Clojure ships with, AFAIAA.

dragoncube03:05:59

great, thank you

dragoncube03:05:22

my use case is: bunch of subjects sending each other messages reacting on those which in result could end up with new messages

dragoncube03:05:34

I guess this is perfect match 🙂

john03:05:25

Yeah, that sounds like it could be a pretty good match.

john03:05:51

Core.async might also match up. Depends on your requirements.

dragoncube03:05:19

btw, is it ok to mix these two? say use core.async to implement action with would be sent with send-off ?

john03:05:17

One of the many benefits of core.async is a kind of light weight thread mechanism, obviating the need for real threads. Agent's send-off is going to depend on a thread pool.

john03:05:28

So if you were using it for that, you wouldn't want to mix those two concerns, at least. But you could def use them together.

john03:05:26

If hundreds of agents are DOSing a few agents with thousands of messages each, and you need to spawn off additional threads from within the agent action, but you'd rather not spawn those many threads, you could implement the action with core.async, yeah.

dragoncube03:05:40

I thought of using agents to manage state and core.async to do IO

john03:05:18

There's many ways to manage state in Clojure. Agents are good when you need to serialize access to the mutation of a particular piece of state.

john03:05:43

A canonical example is a logging daemon that different threads can dump logs to

john03:05:41

And using send with agents is for mostly cpu bound work, while send-off is better for io bound work.

noisesmith03:05:24

@dragoncube one thing to watch out for in your description is that agents don't own any logic - all they own is their current state and optional validator, watcher, error-handler

noisesmith03:05:00

they aren't a black box entity that handles messages, they are a transparent data structure that you send any function to that you like

john03:05:45

@noisesmith what's your take on the mixing of agents with core.async. Are there any gotchas with regard to threads inside go blocks, etc.?

noisesmith03:05:36

don't call await inside a go block ?

noisesmith03:05:21

core.async mixes better with async/thread (which you can park on), but I guess you could try to do something fancy with a validator or watcher that sends messages to a channel... it feels like it would get messy though

qqq05:05:22

(ring.adapter.jetty/run-jetty
   (ring.middleware.resource/wrap-resource #'app "prod")
   {:port 5000
    :join false})

qqq05:05:32

is there a wa to tell wrap-resource to serve "index.html" at "/" ?

branch1408:05:32

Is it prossible to proxy PersistentArrayMap?

noisesmith13:05:52

@branch14 it makes more sense to implement each of the interfaces / protocols that hashmaps implement (there's a bunch) - ztellman made a library to simplify this

noisesmith13:05:35

proxy doesn't fall back on superclass behaviors automatically iirc - you have to explicitly use proxy-super for each method

noisesmith13:05:27

clojure makes concrete inheritance difficult, it's intentional

mpenet13:05:19

And that s probably why cursive (among others) is written in part in kotlin...

mpenet13:05:52

There isnt that much missing sadly

branch1413:05:37

@noisesmith Thx for the hint. I guess you're referring to def-map-type of potemkin. I'll look into it.

noisesmith14:05:14

you could also try defrecord, implementing invoke on the IFn interface - it would be simpler if it works

noisesmith14:05:44

@branch14 just use a defrecord

+user=> (defrecord Foo [] clojure.lang.IFn (invoke [this key] (or (get this key) (str "no value for " key " in map."))))
user.Foo
+user=> ((map->Foo {:a 0}) :a)
0
+user=> ((map->Foo {:a 0}) :b)
"no value for :b in map."

branch1414:05:24

@noisesmith Oh nice! I've to try this and see how it pans out.

qqq14:05:52

is there a way to use reagent.core/'s ratom in plain clojure instead of just cljs ?

weavejester14:05:34

@qqq what benefit would ratom have over atom in Clojure?

qqq14:05:02

it's reactive

qqq14:05:09

if I define ratom b to define on ratom a

qqq14:05:15

then when I update a, b gets auto updated

qqq14:05:26

I think the 'frp' part of ratom is useful outside of react

weavejester14:05:08

Oh, you mean outside of the DOM?

qqq14:05:30

FRP is just functional reactive programming; it's usefalbe outside the DOM right? 🙂

curlyfry14:05:42

@qqq Would add-watch help with achieving what you want to do?

qqq14:05:23

@curlyfry: are the semantics the same?

qqq14:05:31

I think add-watch ensures that , sometime in the future, atom b is updated

qqq14:05:43

but ratom guarantees: when you update ato ma, before you can deref b, b is updated

weavejester14:05:02

I wrote an FRP library, Reagi, a while back. But it convinced me that FRP suffers from complexity at scale.

qqq14:05:20

java.net.URLClassLoader$1.run          URLClassLoader.java:  362
                              java.net.URLClassLoader$1.run          URLClassLoader.java:  368
                         java.net.URLClassLoader.access$100          URLClassLoader.java:   73
                        java.net.URLClassLoader.defineClass          URLClassLoader.java:  467
                java.security.SecureClassLoader.defineClass       SecureClassLoader.java:  142
                          java.lang.ClassLoader.defineClass             ClassLoader.java:  763
                         java.lang.ClassLoader.defineClass1              ClassLoader.java     
                            java.lang.ClassLoader.loadClass             ClassLoader.java:  357
                            java.lang.ClassLoader.loadClass             ClassLoader.java:  424
                          java.net.URLClassLoader.findClass          URLClassLoader.java:  381
       java.lang.ClassNotFoundException: com.fasterxml.jackson.core.FormatFeature
         java.lang.NoClassDefFoundError: com/fasterxml/jackson/core/FormatFeature
clojure.lang.Compiler$CompilerException: java.lang.NoClassDefFoundError: com/fasterxml/jackson/core/FormatFeature, compiling:(cheshire/factory.clj:53:5)
             clojure.lang.ExceptionInfo: java.lang.NoClassDefFoundError: com/fasterxml/jackson/core/FormatFeature, compiling:(cheshire/factory.clj:53:5)
    file: "/tmp/boot.user5060282787292643425.clj"
this is me trying to build a jar -- how do I figure out what's using fasterxml.jackson.core ... and how do get rid of it?

weavejester14:05:14

It’s likely a dependency conflict. Check lein deps :tree, @qqq

weavejester14:05:01

Usually it happens when one library depends on Java library version X, and another library depends on version Y.

qqq14:05:02

hmm, it's boot, but I'll look into boot dependencies

qqq14:05:14

ah, I have rin 1.5.0 and 1.6.0-RC1

qqq14:05:25

s/rin/ring/ ; will look into that

weavejester14:05:54

One library wants an older version of Jackson that doesn’t have FormatFeature, and because the dependency is “closer” it’s overriding the later Jackson dependency.

qqq14:05:05

I'm a big fan of http://shaffner.us/cs/papers/tarpit.pdf ... which is basically a FRP system where eacn node is a db

qqq14:05:15

@weavejester : yeah, Jackson issue resolved; thanks!

lilactown15:05:48

how do I re-require a file through the repl?

lilactown15:05:00

or reload it or whatever

weavejester15:05:02

(require 'foo.core :reload)

weavejester15:05:25

:reload-all will reload the file and dependencies.

lilactown15:05:37

i'm trying to follow http://pedestal.io/guides/developing-at-the-repl and the instructions are not helpful

weavejester15:05:08

There’s also the tools.namespace library: https://github.com/clojure/tools.namespace

weavejester15:05:25

Which has a refresh function. That deletes, then reloads, any changed namespaces.

lilactown15:05:30

is there a way to automate this?

lilactown15:05:37

I'm using emacs with cider

lilactown15:05:11

when I use e.g. figwheel, it seems to reload it without re-requiring

weavejester15:05:46

@lilactown Have you looked into the reloaded workflow?

weavejester15:05:26

@lilactown Cider has a cider-refresh function that can work well with that.

lilactown15:05:40

reloaded workflow?

weavejester15:05:31

There might be a pedestal template for it.

weavejester15:05:42

Or maybe pedestal supports it natively…

weavejester15:05:54

I’m not sure. I don’t use Pedestal I’m afraid 🙂

lilactown15:05:28

thanks i'll look into it

weavejester15:05:51

If you decide to use Ring, then I can give you options 🙂

weavejester15:05:33

You might also want to ask in the #pedestal channel

lilactown15:05:54

I asked there too

lilactown15:05:02

it seemed like ring was a lot lower level?

lilactown15:05:10

i'm researching using clojure + graphql, and the lacinia project has an integration with pedestal: https://github.com/walmartlabs/lacinia-pedestal

quan05:05:53

lilactown: i try lacinia with ring https://github.com/tentamen/try-lacinia

lilactown14:05:51

cool, thanks!

lilactown15:05:39

but i'm not really tied to it. how does ring compare?

weavejester15:05:38

I’m somewhat biased, but my general impression of the difference is that Ring started from a synchronous approach to HTTP, and Pedestal started from an asynchronous approach.

weavejester15:05:23

They both have similar goals. Pedestal includes things like its own router, whereas Ring foists that off onto third-party libraries.

weavejester15:05:00

I’d tentatively suggest that Ring is easier to get going with.

weavejester15:05:48

Lacinia has support for Ring as well as Pedestal, it looks like.

lvh17:05:07

Is there a way to spell partition as a transducer without using a third party lib?

lvh17:05:56

looks like it’s just partition-by and partition-all but not regular partition

noisesmith17:05:24

partition-all and a count based filter?

noisesmith17:05:59

(comp (partition-all 3) (filter #(= (count %) 3)))