This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2018-02-13
Channels
- # beginners (50)
- # boot (27)
- # bristol-clojurians (7)
- # cider (30)
- # clara (1)
- # cljs-dev (130)
- # cljsrn (14)
- # clojure (179)
- # clojure-austin (6)
- # clojure-greece (2)
- # clojure-italy (4)
- # clojure-spec (19)
- # clojure-uk (54)
- # clojurescript (64)
- # core-async (3)
- # data-science (1)
- # datomic (66)
- # duct (11)
- # emacs (5)
- # figwheel (1)
- # fulcro (26)
- # funcool (7)
- # jobs (1)
- # jvm (6)
- # keechma (5)
- # lein-figwheel (5)
- # luminus (5)
- # lumo (1)
- # off-topic (93)
- # parinfer (37)
- # pedestal (15)
- # protorepl (10)
- # re-frame (42)
- # reagent (12)
- # shadow-cljs (71)
- # spacemacs (3)
- # specter (7)
- # vim (8)
- # yada (9)
surprised because I've written a rules engine and it never occurred to me to call eval, not because I know anything about clara-rules
in general, if you are calling eval over and over again, the better thing to do is to call eval once to generate a function, then invoke that function over and over again
=> (distinct #{1 2 3})
UnsupportedOperationException nth not supported on this type: PersistentHashSet
neat@hiredman It calls eval
to compile functions around the provided code. It supports fairly arbitrary forms in the rule syntax, so it isn’t something as straightforward as some basic interpreter. Also, that may suffer in terms of performance even if it was. As far as rules engines on the JVM go, Drools has similar rule “eval” going on as in Clara.
I agree that ideally there’d be less things eval
ed. Clara actually does attempt (and could do more) to avoid eval
of equivalent forms.
What is striking me as odd right now though is just that many calls to eval
on separate forms is slower than doing a batch of them via eval
eg
(eval f1) (eval f2) (eval f3) .... (eval f-n)
;; is slower than
(eval [f1 f2 f3 ... f-n])
Where each f
is an un-eval’ed formI think I have been failing to see the number of classes needed in the first example vs the second
Each eval
makes a class then I guess. And when you put forms together, you reduce that count?
I think I can easily see this distinction just by experimenting with the cardinality of classes created via eval
using *compile-files* = true
in the REPL
Thanks @bronsa and @hiredman for setting me straight. I guess it was a fairly dumb question afterall 😛
so, I have some perhaps misguided notion of making docker smaller services with clojure and running them with kubernetes... it seems that I am doing too much with individual clojure projects, mainly because they become weird multipurpose uberjars and are hence harder to reason about... any thoughts and is this an anti-pattern?
as a side note, I found https://github.com/Quantisan/docker-clojure and in there it is said "Compiling an uberjar and running it via java -jar or using lein run trampoline would be much more memory-efficient." ... this is a bit confusing to me...
is memory a primary concern? Isn't building smaller things and dockerizing them a plus?
I guess I'm looking for pointers on how to make my larger projects more 'composable' themselves, and docker comes to mind, but I may not be in touch with the best approach.
Does Java have any builtin kv store? I'm looking for something besides "use the file system" to store a bunch of kv pairs
@macrobartfast I think you’re really asking about the pros and cons of building microservices versus monoliths.
@macrobartfast of how would a docker image containing all your code plus a jvm use less memory than a jvm plus a jar containing all your code?
For which there are pros and cons, and in the specifics it will depend what you’re building and how large you intend it to scale.
@qqq not that I’m aware of. I’ve been using H2's MVStore with great success so far (http://www.h2database.com/html/mvstore.html)
@noisesmith well, I guess each docker image has the overhead of a small os of sorts, Alpine in this case.
No, that’s really not how docker works.
Ah, ok...
point being that anything that can be done with N docker images can be done with N fat jars
It’s kernel namespace mechanisms to isolate processes.
the advantage docker gives you (if any) isn't about resource usage - it's about automation and simplicity of deployment
which is conceptually appealing
though every time I get into docker I rabbit hole into networking issues etc
which makes me wonder if java had the container thing going all along in application servers and so on.
that is, the jar as a sort of unit that docker now provides in cases
@gonewest818 that sounds right...
@gonewest818 it is probably not a discussion for here.
what's missing with a jar is the deployment and OS tooling (keeping the service running, automated startup and shutdown) - that's not extremely hard (I do it with jsvc / commons daemon), but I see how docker has a similar appeal
although I was just sanity checking to make sure there isn't a commonly used alternative strategy clojure devs use for bigger apps before I waste 2 weeks learning about docker/kubernetes/etc.
but you'll also simplify things in the docker world if you make a docker image that uses a jvm and a jar, instead of leiningen plus jvm plus resolving deps and building on startup etc.
well, I think https://github.com/Quantisan/docker-clojure has that underway, from the looks of it.
like, do people who write C code make docker images that contain gcc, that install all the deps and compile the app from scratch on startup? I guess they could do that but I'd suggest they are making things more complicated than needed
I think I'll go the docker route for now because then I can pull down containers that do things I need, and they can use whatever language they want to.
anyways, off topic, as said, I guess.
thanks for the input!
Yes, you’ll spend some time scratching your head about Docker but worth the effort in my experience. Ask questions on #docker as you need…
@qqq in memory, or on disk? How big is the kv data?
I'm trying to split a range if the difference is greater than one. is there a good generic function for this? e.g.
(partition-with #(> (- %2 %1) 1) [1 2 3 6 7 8 9 15 16 17 20]) => [[1 2 3] [6 7 8 9] [15 16 17] [20]]
I'm aware of partition-by but it doesn't quite do what I want, though it's close(defn partition-between [pred? coll]
(let [switch (reductions not= true (map pred? coll (rest coll)))]
(map (partial map first) (partition-by second (map list coll switch)))))
https://stackoverflow.com/a/23221442/3616102Let's say I have a naive apply
implementation:
(defn my-apply [f args]
(loop [f f
args args]
(if (seq args)
(recur (partial f (first args))
(rest args))
(f))))
(my-apply + (range 10000))
;;=> Throws StackOveflowError
I'm wondering why this throws StackOverflowError.
Is this something related to partial
?the f
you output will be nested as many times as there are arguments, so with 10000 args you’ll have a call stack 10000 layers deep, which will overflow
guys, I'd need to compare 2 vectors and I thought of clojure.data/diff
, but I want to compare the elements in a custom way
what would you suggest?
@erhardtmundt do they have the same size or are they ordered somehow ? If so, map
can accept multiple collections. Otherwise, you can convert them into set and use clojure.set
@fmind the 2 vectors are not guaranteed to have the same size and their elements are hashes
I'd like to use one of their values to identify them
@erhardtmundt I think you need to be more clear about the comparison you want to do before we can advise.
I have something like [{:id 1 :foo "foo" :bar "bar"}]
[{:id 1 :baz "baz"}]
I want to compare the hashes I have in each vector and just check for id
so I would expect diff
to return (nil, nil,
any of the 2 )
@erhardt.mundt compared by :id
? Or compared by position in the vector?
compared by :id
@erhardt.mundt group-by
is probably your first port of call, so something like: (map (fn [[k v]] (map hash v)) (group-by :id (concat coll-a coll-b)))
Actually, even better would be to do vals
before map
, so like (map #(map hash v) (vals (group-by :id (concat coll-a coll-b))))
Essentially you're grouping the maps by their :id
, and then doing the operation on them in a known state.
:thinking_face:
what is that supposed to do?
sorry if I'm a bit slow, but I'm not too experienced
no need to apologise 🙂 by the way, you might find the #beginners channel more appropriate
thanks
(vals (group-by :id (concat coll-a coll-b))
should return a vector of elements which are in turn a vector and contain either 1 or 2 hashes (it depends if it's shared or not)
am I correct?
=> (group-by :id [{:id 1 :foo 2} {:id 2 :foo 3}])
{1 [{:id 1, :foo 2}], 2 [{:id 2, :foo 3}]}
=> (vals (group-by :id [{:id 1 :foo 2} {:id 2 :foo 3}]))
([{:id 1, :foo 2}] [{:id 2, :foo 3}])
vals
returns a sequence (not a vector) containing the values of the map returned by group-by
yeah cool, so the sequence has 2 1-sized vectors inside
just because they have no shared "record"
otherwise there would be 2-sized vectors, correct?
what puzzles me is the (map #(map hash v) (vals...))
part
what is v
bound to?
oh, ok
and why do you suggest to hash the elements of the 1-or-2-sized vectors?
ah i think @U09LZR36F was misguided by the use of the word 'hash'
my fault 🙂
note that there is a hash-map
function too, which is how you programmatically create a map
cool!
@erhardtmundt if you can guarantee there will only ever be 2 items in a group, you could call clojure.data/diff on it instead.
@U09LZR36F which group are you talking about?
@erhardt.mundt after you've done group-by
yeah, it's gonna be 2 vectors, so I guess the maximum size of the groups is 2
Try the code:
(map #(apply clojure.data/diff %) (vals (group-by :id (concat coll-a coll-b))))
🙂
@erhardtmundt What do you mean with hashes in "I want to compare the hashes I have in each vector..."?
I come from a ruby world so that's the case
apologies 🙈
So: In clojure we'd call them maps. Never hashes. Hence you got the answer with using hash
function. Which is probably not what you wanted
yes, indeed
good thinking, I should've probably called them maps
(defmacro defthing [name ,,,]
`(def ~(-> name (with-meta {:arglists '([{:keys [k1 k2]}])}))
,,,))
(defthing foo
,,,)
fails on the call to defthing
with 'can't resolve symbol k1'
couple of questions:
- (probably more pragmatic) is there a cleaner way to attach arglists to the generated var?
- (probably more interesting): why does it work when I change it to ''([{:keys [k1 k2]}])
? (as in, two single quotes)my intuition was that it'd only need one because the below works:
(def ^{:arglists '([{:keys [k1 k2]}])} foo
,,,)
the unquote returns a symbol with the metadata quoted - does that mean it's eval'd as part of the def
?
ok - think the crucial step I'm missing here is why
`(def ~(-> 'foo (with-meta {:arglists '([{:keys [k1 k2]}])})))
unquotes the metadata?that quote is only there to prevent evaluating the list as a function call at macroexpansion time
same as why
`(do ~(do 'a))
is incorrect if you want to return the symbol 'a
from a macrois it possible, passing a string and getting back the function ? something like
(defn ns->fn [ns] (some-way ns))
((ns->fn "clojure.core/+") 1 2)
=> (deref (resolve (symbol "map")))
#object[clojure.core$map 0x203dd56b "clojure.core$map@203dd56b"]
Guys need some help with some java interop calls I need to provide a byte array as in [B
into the constructor but can't seem to figure out the right signature
(ns Response
(:gen-class
:implements [some.class]
:state state
:init init
:constructors {[String] []}))
(defn -init
[message]
[[] message])
@firstclassfunc do you need a new class or just a regular byte array?
ohh, nevermind, I guess you’re asking how to provide the byte array as an argument to the gen-class
@schmee Yea I am trying to extend an existing Java class but probably have to find another way to do this.
@firstclassfunc I think this is the right syntax: :constructors {[String] ["[B"]}
but unless you’re doing something out of the ordinary you often don’t need to use gen-class. if you’re implementing an interface, use reify
, if you need a concrete class, use proxy
but I’m not sure how those work with primitive arguments, so maybe gen-class is called for in this case
@schmee you are awesome that worked! thanks so much.. I am working with a Java library that I want to extend with Clojure so I need to create a new class..
here is a good read about all this stuff: https://puredanger.github.io/tech.puredanger.com/2011/08/12/subclassing-in-clojure/
does anyone know why https://clojurians-log.clojureverse.org/clojure/index.html stopped in Nov 17?
i’m told it’s a known issue and is being worked on. the logging is apparently still happening but the searchable website isn’t
Is there a way to get lein test
to tell you what tests have been selected if a selector is in effect, or what :all
consists of if no selector is in effect?
@gonewest818 you can calculate this is a repl, by filtering all vars from all namespaces based on which ones have a :test
metadata, then out of those filtering the ones that also have your selector as a metadata
I don’t think there’s anything in leiningen to do this for you though
(oh NB you also need to ensure you require all test files first too)
I see, okay.
user=> (->> (all-ns) (mapcat ns-publics) (filter (comp :deprecated meta val)))
([agent-errors #'clojure.core/agent-errors] [clear-agent-errors #'clojure.core/clear-agent-errors] [add-classpath #'clojure.core/add-classpath] [replicate #'clojure.core/replicate])
(showing deprecated instead of test, since this repl has no tests loaded)thanks for the example!
I had no idea agent-errors was deprecated…
oh, agent-error instead of agent-errors, haha
Is there a neat way to apply some->
to a sequence? Like (some-> foo [f1 f2 f3])
. some->
is a macro so apply
doesn’t…apply.
you could make a macro that does that, but it would require the sequence to be known at macro expansion time
you could make a reduce with the same behavior (reduce (fn [prev f] (if (nil? prev) (reduced prev) (f prev)) input fns)
(ins)user=> (defn reduce-some
[v fs]
(reduce (fn [prev f]
(if (nil? prev)
(reduced prev)
(f prev)))
v
fs))
#'user/reduce-some
(ins)user=> (reduce-some 0 [inc inc inc inc])
4
(ins)user=> (reduce-some 2 [* * * *])
2
(ins)user=> (reduce-some 2 [inc :foo inc])
nil