Fork me on GitHub
#clojure
<
2018-02-24
>
qqq02:02:13

is there a way to define a cljc macro that: 1. when expanded in clojure, uses clojure.spec.alpha 2. when expanded in cljs, uses cljs.spec.alpha so I have a macro which calls functions from spec, but I need it to use clojure.spec.alpha or cljs.spec.alpha depending on if it's used in clj or cljs

mfikes03:02:28

@qqq I would probably use ClojureScript’s ability to alias clojure.* to cljs.* and then in my ClojureScript namespace require clojure.spec.alpha so that it then really requires cljs.spec.alpha while simultaneously setting up an alias from the former to the latter. This is illustrated in this gist https://gist.github.com/mfikes/3ed89b767048e109891464f1f7e7151b

mfikes03:02:40

In other words “pretend” that there really is only a clojure.spec.alpha namespace and ignore the fact that in one environment it is really named cljs.spec.alpha. You can also avoid the difference for keywords if you, say use things like ::s/invalid in your runtime code (it will qualify to the right keyword in Clojure and in ClojureScript.)

nicoschneider06:02:31

hi everyone, i’m looking for a nice solution to a hopefully simple scenario. i have several resources in my app like users, orders etc, and a bunch of crud actions surrounding them. they’re implemented using records. i’d like to be able to define some events for them, for example the 4 crud actions (“order created”, …). for those events, i’d also have to be able to define multiple “listeners” which are called with the event data when one is fired. i’ve looked into several things, using re-frame on the server, tinkering with core.async, but i can’t seem to be able to code something satisfactory up. how is something like this usually implemented? any pointers?

gklijs08:02:46

@nicoschneider it's not really clear to me what problem your trying to solve. You could use Kafka, have different types of events on different topics, and expose them on a lacinia-pedestal graphql endpoint for some front-end?

gklijs08:02:54

I made a poc running at http://sys3.open-web.nl:8181 like that, using re-frame with re-graph for the front-end.

eskos08:02:47

Kafka is imho comparable to tackling the problem with a bazooka. Sure it's great when it works but managing Kafka cluster is a huge pain; Some MQ is probably what you want instead of general distributed message log system. That said, I don't quite understand either what the problem is that you're trying to solve.

gklijs08:02:16

That's why I asked, maybe using transit and send different kinds of maps over websockets is enough

nicoschneider08:02:43

it mostly concerns various events during a plain old ring request handle

nicoschneider08:02:31

while crud-ing the resources i’d like to isolate some sideeffecty things like emails and file writes based on what happens to the “models”

nicoschneider08:02:42

i’m struggling with finding a good architecture for this

gklijs08:02:27

Seems like a websockets, with different handlers depending on the type will do then?

nicoschneider10:02:42

@gklijs i would love to, but i can only add websockets as progressive enhancement for modern clients. it’ll run on old machines and/or behind excessive firewalls which apparently block websockets. i already had to go to great lengths to make transit/edn work, i don’t wanna get into the details. in the end, it’ll have to all happen in the ring handler, so i’m looking for a sane concept ^^

gklijs10:02:27

You can use sente then and fall back to ajax when websockets can't be used

nicoschneider10:02:39

i actually tried that, might be that i’m too inexperienced, but for some reason it didn’t switch to long polling on the test devices

nicoschneider10:02:29

i might try that again, but i’d need to change a lot of code to essentially move the events to the client

nicoschneider10:02:38

or rather, have them be fired by the clients

nicoschneider10:02:07

actually, in some cases i’d like them to be private/opaque, which would mean leaving them server-side only anyway

nicoschneider10:02:20

i might’ve misstated my problem … it’s not so much about http or the network, or a server/client communication question, but a software architecture one. i don’t need/have the time, expertise or resources to set up one of those event streaming processes a la kafka etc, where i imagine much of the solution to my problem is moved to the tech stack. i’m just looking for inspiration regarding modelling an easily extensible “event” system, where the events are basically just sideffects like emails or saving an audit trail

nicoschneider10:02:17

e.g. when an order is created, call these handlers

gklijs10:02:23

You could have something like a rest endpoint, and have the clients call it each minute?

nicoschneider10:02:52

as i said, it’s not about the http communication or having clients send the events

nicoschneider10:02:05

they’re fired after/before something happens to resources that are exposed via http

gklijs10:02:48

So what's it about then? Syncing the data available for the consumers on the back end?

nicoschneider10:02:02

no, about the architecture/concept of the events implementation

nicoschneider10:02:15

currently, i have a few extra function calls strewn in the handlers, where needed

nicoschneider10:02:19

what i’d like to be able to do is fire a “generic”, if you want, event, say (events/fire! :shop/order.created order) that would call the associated listeners

nicoschneider10:02:58

i’m looking for ideas on implementations 🙂

luskwater12:02:17

@nicoschneider What about using (add-watch ,,,) on whatever atom represents your state, (data/diff ,,,) to see what changed, and then dispatching the event via queues/channels or the like?

nicoschneider13:02:06

@luskwater that’d work for a few things where i have to track individual entities, yeah … i need something “general” as well, regardless of what changed etc. queues would be ideal, i have event handlers which generate files

luskwater13:02:16

Sounds interesting: might be interest in a lightweight system for that, but I don’t know of anything myself.

qqq15:02:12

Is there a builtin for:

(defmacro et [& body]
          `(try (do ~@body)
                (catch Throwable e# nil)))
Initially, this looks bad, as it silently eats the Throwable and returns nil. However, I often have situations with if / cond, where the test itself may throw an exception (in which case it should "fail") Is there a builtin for this? Is there a better way to do this? Is the fact I'm using this suggests something else is goign wrong

ghadi19:02:17

;; swallow exceptions
(defmacro ignoring
  [exc & body]
  `(try ~@body
        (catch ~exc e# nil)))
just wrote that in a project

joelsanchez00:02:17

thanks for this, I swallow exceptions every once in a while, this comes in handy. I named it swallow following the spirit of spit and slurp

noisesmith15:02:25

go narrower in two ways: only catch the specific exception you might see (or directly prevent it and return nil) and don't wrap a whole body, wrap a specific predicate. If the exception is NPE you can just do #(some-> % (pred?))

noisesmith15:02:45

I've seen big long term problems caused by someone catching Exception (or even worse Throwable) and returning nil, because they expected NullPointerException - and thus real problems we need to fix are ignored

yogidevbear21:02:41

Hi guys. I'm looking for an idiomatic way to update the value in a segment within a vector. E.g. change [0 0 0 0 0 0] to [ 0 1 1 1 0 0]

schmee21:02:26

@yogidevbear Specter is your best friend here! 🙂 gimmie a sec and I’ll make an example

yogidevbear21:02:34

Would it make sense to use a combination of something like map-kv and subvec?

sundarj21:02:21

here's a plain Clojure version:

user=> (reduce-kv (fn [result i v]
                    (conj result (if (#{1 2 3} i) 1 v)))
                  []
                  v)
[0 1 1 1 0]

yogidevbear21:02:00

Nice work Sundar 👍

schmee21:02:06

user=> (def v [0 0 0 0 0 0])
#'user/v
user=> (setval (srange 1 4) [1 1 1] v)
[0 1 1 1 0 0]

yogidevbear21:02:34

Nice. Thanks @schmee. Is Specter Clojure or ClojureScript or both?

yogidevbear21:02:04

Cool, thanks. I've give that a go

schmee21:02:12

the author answers most of the questions in #specter, so if you run into trouble just ask there 🙂

nathanmarz21:02:18

@schmee @yogidevbear even simpler: (setval [(srange 1 4) ALL] 1 v)

yogidevbear22:02:54

Hi @U173SEFUN. Do you know if there is a similar approach for doing the same thing to a vertical column range within a vector of vectors? e.g.:

[[0 0 0 0 0]
 [0 0 0 0 0]
 [0 0 0 0 0]
 [0 0 0 0 0]
 [0 0 0 0 0]]
to
[[0 0 0 0 0]
 [0 0 1 0 0]
 [0 0 1 0 0]
 [0 0 1 0 0]
 [0 0 0 0 0]]

nathanmarz22:02:38

one way is (setval [(srange 1 4) ALL 2] 1 data)

nathanmarz22:02:05

can also abstract it like this:

(defn mat-elems [row col end-row end-col]
  (path (srange row (inc end-row)) ALL (srange col (inc end-col)) ALL))

(setval (mat-elems 1 2 3 2) 1 data)

yogidevbear22:02:02

That is really awesome

schmee21:02:10

hah, seems there is always a simpler way 🙂

joelsanchez23:02:23

is there some limit on the number of futures? is it a good idea to have many futures?

noisesmith23:02:41

@joelsanchez - futures using an expanding pool of threads, but each future monopolizes a real thread

noisesmith23:02:54

so it's definitely possible to create so many that your app grinds to a near halt

noisesmith23:02:55

@joelsanchez future's are great when you need to do a one off task in a new thread, but they aren't a good plan if you want to make a large number of threads in parallel - you can look at the claypoole library for that as one good example

alexstokes23:02:28

anyone have any data on the overhead for keeping data in a set vs some seq?

joelsanchez23:02:48

thanks, that confirms my thoughts, I don't really have a need for many futures so I just won't 😛

alexstokes23:02:12

i suppose my real question is just how things are checked for equality in a set? if i conj #{1 2} 3 will we iterate over the set in linear time?

noisesmith23:02:51

@alexstokes the main feature of sets is that they are indexed, uniqueness comes pretty cheap once you have that property

noisesmith23:02:11

checking if an item is in a set is about the same cost as looking up an item in a hash-map

alexstokes23:02:37

you wouldn’t know where i should look for that code do you?

alexstokes23:02:44

just curious how clojure handles it

alexstokes23:02:23

a simple implementation could just re-use hash-map and ignore vals

noisesmith23:02:06

@alexstokes reading that, you are right! it has a local, "impl" and when you conj an item to a the set, it does (assoc impl x x)

noisesmith23:02:48

that's all implementation details that could change in a future version of course - but the fact that lookups are cheap is an intended feature that will stick around

alexstokes23:02:17

yeah thats what im after

alexstokes23:02:31

i was using a seq for some children in a tree but i really want the semantics of set

alexstokes23:02:43

wanted to make sure i wasn’t gonna do anything silly by using one