This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2017-06-06
Channels
- # aleph (15)
- # beginners (40)
- # boot (14)
- # cider (90)
- # cljs-dev (132)
- # cljsrn (25)
- # clojars (7)
- # clojure (188)
- # clojure-chicago (4)
- # clojure-dusseldorf (1)
- # clojure-greece (9)
- # clojure-italy (43)
- # clojure-russia (16)
- # clojure-sg (7)
- # clojure-spec (39)
- # clojure-uk (81)
- # clojurescript (170)
- # component (5)
- # core-async (7)
- # cursive (49)
- # data-science (65)
- # datascript (3)
- # datomic (27)
- # graphql (3)
- # hoplon (4)
- # instaparse (56)
- # klipse (129)
- # leiningen (1)
- # lumo (28)
- # off-topic (4)
- # om (15)
- # onyx (54)
- # overtone (7)
- # pedestal (7)
- # re-frame (9)
- # reagent (72)
- # ring (33)
- # ring-swagger (2)
- # spacemacs (1)
- # untangled (19)
- # vim (2)
- # yada (12)
in particular, I don't even knowwhat 'dependency' and 'injection' mean in the clojure context
@qqq it's not a term used often in the context of clojure, but I would presume it means what it means in other contexts -- instead of a function/object reaching outside its local context to acquire a resource (dependency), the dependency is passed in to the function as an argument (in OO, typically at object creation via the constructor). I would say that the spirit of DI is used quite often in clojure, since we often avoid global state and instead prefer to pass functions as arguments, with the expectation that the passed function will perform some service to the function being called (we also pass database connections, etc).
I think the best example of DI in clojure is ring - when you run a ring server you can deploy to tomcat or run self hosted without editing code, thanks to the injected dep of the http server
or I guess that's more like the kind of thing java folks mean when they talk about di (eg. spring)
I think I get it now. For something like system, we have this map {:web-server ... :db-server ... :blah-server ... } which we pass around. Otherwise, we'd have to globally define a web-server, db-server, blah-server, then require the right namespace, and ensure everything is loaded in the right order. In the "DI" method, this "ordering" is not as important, since we can construct the *-server whenever we want, then just pass it all in as a map. Is this roughly correct ?
https://www.youtube.com/watch?v=13cmHf_kt-Q <-- are 'components' basically 'objects done right' ?
I would not say that, no. Components address a very specific application lifecycle use case — they’re not any sort of general purpose “object”.
Clojure already addresses some aspects of OOP in a “better” way (arguably, depending on your p.o.v.). It has a la carte polymorphism, for example.
@seancorfield : you're absolutely right; I only watched part of the talk when making thea bove statements
Is DI even a thing in clojure (or any dynamic language for that matter)? Typically the thing you inject in java is some sort of state for an object, and you do it because if you dont theres no other way to get ahold of it for the purpose of mocking in a unit test. Clojure uses functions not objects, and dynamic languages can easily mock dependencies without having to resort to DI.
One could think of DI is a way of providing a sort of partial application in languages without HOFs. Even in a dynamic language, the explicit declaration of the dependencies required by a unit of execution is not a bad thing. My years of monkey-patching Ruby apps, while fun, were not particularly principled.
Having a function “reach out” to some implicit state leads to less reasonable code, and I think the point of Stuart’s components is to make that dependency explicit and reasonable.
I'm a huge fan of https://github.com/weavejester/integrant. To me it feels like the sweet spot between mount and component. It feels more Clojurey (less OOP-ish) than Component, but has the same benefits.
greetings fellows, I’m looking for a quick’n’dirt db to use with clj, with the less friction possible. Something like the old days’ embedded hsqldb but without the sql 😄 any advice?
why not just use that or sqlite? robust, well-understood, and can be used as a k/v store if needed
Hi! I’m just writing a piece of code that relies on a given set not suddenly changing its traversal order, and I realised that that might be an implementation detail and not guaranteed by sets' contract.
or should I expect to possibly get {1 2, 2 1}
because s doesn’t have to have a consistent order?
call seq several times on the same unordered collection, and the order will always be the same
Thanks @leonoel . It seemed kind of obvious when I was writing the code, but come review time I was like ‘wait I sec, I don’t actually know that’
You also suggested suggested a good safety measure: I can actually throw in one explicit seq
and use the result in both places.
That way, I won’t have to wonder I won’t have to wonder again if the order is stable
Can someone point me at an example of using pprint and controlling where the wrapping happens. I'm doing some EDN config generation and I'd like to shape it a little.
The main docs and api are quite intimidating.
@frederic interestingly it doesn't work if collections are equal, they have to be identical
@olivergeorge I think with clojure.pprint your options for customization are really just *print-right-margin*
and *print-miser-width*
I've watched through stuart sierra's component; and am convinced it's a good idea. What does "system" provide over "component" ?
qqq: I hadn’t heard of “system” until now, but having looked at the repo my concern would be the effort required to keep it up to date.
personally I prefer mount over component, but I don’t have a reason other than the differences listed by the the author: https://github.com/tolitius/mount/blob/master/doc/differences-from-component.md
@U4PUTN69G : in other words, is your concern with 'system' the main 'system' repo has to wrap all the libraries its using into components therefore, if the main 'system' repo is not up to date, you're forced to use old libraries ?
You’re welcome. Yes, basically that’s the concern.
how to access a method from the super-class? JFrame
inherits from Component
and I need to access getWidth
in Component
recently I found out that the avg number of commits on clojure itself, is about 10 per month. Comparing it to other langs like Golang, it is very small. I really want to know your opinion on this. how do you guys see the future ?
As in, perhaps the small number of commits reflects waning momentum in the Clojure community?
clj dev is mostly lead by "core", and mainly behind closed doors, always been like this
clojure is not driven by adding features or growing the language outwards as an explicit goal.
90% of what I use was in 1.0
that's another subject, a disscussion about spec/core.async design in the open might have been nice imho
I mean, I don't know much about golang, but two languages I know of that have gone through major revisions in the last few years C++ and JavaScript
And these revisions addressed (or attempted to address) longstanding complaints about the language by its users
I just don't know of any such complaints about Clojure
golang repo includes all the compiler dev + some of the tooling, I guess if you add openjdk/oracle-java stuff to clojure it'd be (sort of) close. I like golang a lot (use it at work happily) but I am not sure the longstanding complaints are getting addressed 🙂 (hi generics, not that I care personnally)
golang and clojure are actually kind of similar about the conservative way of (not) adding features
Something missing imho is really open design discussions (confluence exists but it's kind of lacking), missing the days where rich was available on irc from time to time to answer questions directly too
But how many people are actually qualified to have those design discussions? When the Clojure community was very small, it attracted a lot of experts (or at least senior devs willing to work on the bleeding edge). Now the community is much bigger, and some of those original folks have moved on (for whatever reasons), it would be much harder to have those discussions “at large”.
Look at the mailing list — compare the quality of discussions from six years ago about new features and/or changes with the discussions of the last year. You can clearly see the shift of expertise level.
That’s to be expected as a language community grows over time.
I think we have a great core language and a strong, stable set of contrib “standard” libraries and any major new features are going to require a huge amount of hammock time. Clojure is a higher quality language because of that.
@bronsa Heh, true, and those design discussions do indeed happen on the -dev list, amongst those who’ve signed CAs and asked to join.
And even major new features of late, e.g. async and spec, are really just libraries that ship with the language. They didn't involve any (major) changes to what was already there
Someone mentioned C++ earlier — that was (and still is) designed by an ANSI Standards Committee and revisions (or at least regular reviews) are mandated by the ANSI process.
(I was a voting member of the ANSI C++ Committee for eight years so I’ll claim reasonable insight into the process)
The community feedback on spec was sufficient to drive the decision to split it into an alpha library to evolve separately from Clojure itself.
I am not sure it's what drove the split. Having it separate is good, but it's unrelated to what I mentioned (initial design).
But I get, the "it's rich baby" and that s how he likes to deal with it. I just wish it was more open.
So, how do you feel about, say, Python in this regard?
Does transit differentiate between longs and integers?
1, (int 1) and (byte 1) all serialize to 1 in the output, I just checked
cool.. thanks @noisesmith
hi all, Is there any tutorial or help about how to secure an API (Rest webservice) with a Certificate?
@alricu There might be something on nginx, which might be easier than using certificates directly with Clojure.
I have a REST webservice working in Clojure; but I do not know how to secure it!!! It has to be something with certificates
The Ring Jetty adapter does have client certificate support.
Though in general web services tend to be secured not through client certificates, but HTTPS + a username/password or a token system like JWT.
Or OpenID for that matter.
If you’re starting from scratch and have no preference, what about HTTPS (so just normal, server-side certificates), combined with basic auth.
I believe Buddy has some middleware for HTTP basic auth
client-side certificates might be a good solution, then. There may be a tutorial about how to add them to nginx, which could prove to be a more general solution than one specific to a Ring adapter.
is there a function (transform-map m f)
that returns a map with the function f
applied to all the values and the same keys?
or do i have to roll my own with seq
, map
, and ... whatever is the inverse of calling seq
on a map?
@adamvh it’s built into a lib called specter
@adamvh (reduce-kv #(assoc %1 %2 (f %3)) {} m)
or (into {} (for [[k v] m] [k (f v)]))
or you can do it via (into {} (map (fn [[k v]] ...) m))
or, to use a transducer (into {} (map (fn [[k v]] ...)) m)
those code snippets change sorted maps to unsorted maps and are quite inefficient https://gist.github.com/nathanmarz/b7c612b417647db80b9eaab618ff8d83#file-results-clojure-1-7-0-clj-L28
with specter: (transform MAP-VALS f m)
@nathanmarz any reason not to show into with a transducer arg for comparison there?
(I assume it would be similar to reduce-kv perf… but don’t know)
that's in the benchmark
it's much slower than reduce-kv
I don’t see it
the last one
(into {} (map (fn [e] [(key e) (inc (val e))]) data))
the into call shown isn’t using a transducer
that paren next to data would need to move one to the left
oh my bad, couldn't read my own code
yeah, transducers are tricky that way
i'll add that to benchmark
but i think it would be much slower than reduce-kv
:thumbsup: - I;m sure specter is still faster, just curious
just cause it has to wrap key/value pairs in []
or write a mapentry transducer and apply it to the reduce-kv example
(defn map-vals [f]
(fn [rf]
(fn [result k v]
(rf result k (f v)))))
(reduce-kv ((map-vals inc) (fn [m k v] (assoc m k (inc v)))) {} data)
@ghadi you mean (reduce-kv ((map-vals inc) (fn [m k v] (assoc m k v))) {} data)
?
that seems to be the same as (reduce-kv (fn [m k v] (assoc m k (inc v))) {} data)
but with an additional layer of indirection
here's benchmark with transducer:
Benchmark: transform values of a small map (500000 iterations)
Avg(ms) vs best Code
68.193 1.00 (transform MAP-VALS inc data)
87.001 1.28 (map-vals-map-iterable data inc)
126.68 1.86 (reduce-kv (fn [m k v] (assoc m k (inc v))) {} data)
129.62 1.90 (map-vals-map-iterable-transient data inc)
142.09 2.08 (persistent! (reduce-kv (fn [m k v] (assoc! m k (inc v))) (transient {}) data))
175.33 2.57 (reduce-kv (fn [m k v] (assoc m k (inc v))) (empty data) data)
270.34 3.96 (into {} (map (fn [e] [(key e) (inc (val e))])) data)
387.06 5.68 (zipmap (keys data) (map inc (vals data)))
420.07 6.16 (into {} (for [[k v] data] [k (inc v)]))
438.79 6.43 (into {} (map (fn [e] [(key e) (inc (val e))]) data))
475.66 6.98 (transform [ALL LAST] inc data)
********************************
Benchmark: transform values of large map (600 iterations)
Avg(ms) vs best Code
116.18 1.00 (persistent! (reduce-kv (fn [m k v] (assoc! m k (inc v))) (transient clojure.lang.PersistentHashMap/EMPTY) data))
121.99 1.05 (persistent! (reduce-kv (fn [m k v] (assoc! m k (inc v))) (transient {}) data))
125.07 1.08 (transform MAP-VALS inc data)
139.34 1.20 (reduce-kv (fn [m k v] (assoc m k (inc v))) (empty data) data)
141.92 1.22 (reduce-kv (fn [m k v] (assoc m k (inc v))) {} data)
147.69 1.27 (into {} (map (fn [e] [(key e) (inc (val e))])) data)
148.12 1.27 (map-vals-map-iterable-transient data inc)
172.44 1.48 (map-vals-map-iterable data inc)
190.33 1.64 (into {} (for [[k v] data] [k (inc v)]))
195.83 1.69 (into {} (map (fn [e] [(key e) (inc (val e))]) data))
222.11 1.91 (zipmap (keys data) (map inc (vals data)))
245.87 2.12 (transform [ALL LAST] inc data)
about 4x slower than optimal for small maps, 30% slower than optimal for larger maps
specter seems dope thanks @nathanmarz 🙂
well, for starters use 1.0.1
but no, don't need to do anything special
i was worried because lein deps
downloaded a jar but i guess cljs knows what to do with those
all deps are jars
(as far as I’ve seen at least?)
this is a stupid question but i wasnt able to find any good explanation this far ..
if i can use an atom to hold a map (hence, any number of data), why id use a ref ? theres any intrinsic disadvantage in storing all state inside a map? (besides the fact that my code can get more organized if i split things up) is there some situation where is clearly better to use separated refs and use dosync
?
im asking this because i think ive seen a cljs app storing all app state inside a (atom {})
if you have high contention for alteration, separate refs will perform better
but if you don’t hit that scenario, atoms are definitely simpler
I’ve never had code that was using a mutable container agressively enough for refs to improve performance, but I’m sure there are scenarios that exist
If you have two atoms representing two different bank accounts, how do you transfer money from one account to another while ensuring that no party ever sees an inconsistent view of who has what money when?
Two refs can be updated in an coordinated fashion so that before, during and after the transaction both states are always providing a consistent view of their states to all parties.
if you are using core.async in cljs, the easiest thing to do is to put all read/writes of accounts behind a single go block, again serializing all actions
With get
, is there a way for me to throw an exception when a key is not found instead of simply providing a default value as the second argument?
Not that I'm aware of, though you could check for the default value afterwards and throw there or pass it through
given get
, you can write a function that uses get
and throws an exception if it returns the not-found value
peregrine.circle=> (.getValue (find {:a 0} :a))
0
peregrine.circle=> (.getValue (find {:a 0} :b))
NullPointerException clojure.lang.Reflector.invokeNoArgInstanceMember (Reflector.java:301)
one way to do it without a new functionnot a very helpful error htough
even if you are using core.async in cljs, core.async on javascript is cooperative, if you don't do any channel takes or puts, you don't yield control to other go blocks
so if you read from one account and write to another, without async operations in the middle, it will execute effectively atomically
@adamvh that's orthogonal
specter is for when you want to change a piece of a data structure and leave everything else the same
@rinaldi there's a good reason why get
returns nil
instead of throwing an exception on missing key though
@hcarvalhoaves Yeah, I'm sure there is. Was just wondering if that would work for my use case.
with exceptions many idioms fall apart - like or
, some->
, etc
i see - so in my case i would run group-by
and then use specter to transform my newly-grouped map
thanks @nathanmarz
hmmm sadly it seems like spectre has its arguments in the wrong order for swap!
but c'est la vie
Hey there, any one have and advice for getting Environ to work on boot? I'm pretty new to clojure, so probably something I'm missing, but I can't seem to get it to work. The issue might actually be setting the right environment in boot.build, but I'm not sure.
@adamvh yea I do something similar in a few spots
anyone have any clever tricks for converting, filtering, or preventing non-EDN from getting into strings produced by pr-str
? especially regexes. (e.g. (edn/read-string (pr-str #"foo"))
)
producing them via pr-str
is NOT a requirement if there's a better way
you could use clojure.walk/post-walk to replace all inputs that are not in the whitelist of supported types with a placeholder
so that [:foo :bar #[object …]]
could become [:foo :bar ::unreadable]
or whatever
it really seems like there should be something built in for this...
there are actual persistence libs, like transit
which allows a per-class config for how to write/read
yeah but I want to use EDN here
it's like you can't safely generate EDN from clojure, which is... weird
transit is a superset of edn - you can safely generate edn, but it’s up to you how to handle data that doesn’t belong in edn
and walk/postwalk really makes this easy