This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2019-02-01
Channels
- # aleph (1)
- # announcements (2)
- # aws (3)
- # bangalore-clj (1)
- # beginners (136)
- # boot (3)
- # calva (89)
- # cider (44)
- # cljdoc (1)
- # cljs-dev (31)
- # clojure (101)
- # clojure-europe (3)
- # clojure-italy (52)
- # clojure-nl (7)
- # clojure-spec (12)
- # clojure-uk (34)
- # clojurescript (62)
- # community-development (46)
- # cursive (25)
- # datomic (6)
- # duct (26)
- # events (6)
- # figwheel-main (4)
- # fulcro (25)
- # graphql (2)
- # jackdaw (4)
- # jukebox (3)
- # kaocha (57)
- # leiningen (31)
- # off-topic (3)
- # onyx (4)
- # other-languages (22)
- # pathom (18)
- # re-frame (9)
- # reitit (3)
- # shadow-cljs (60)
- # spacemacs (9)
- # speculative (22)
- # sql (39)
- # tools-deps (45)
- # vim (37)
when writing a clojure library, should we just have all the dependencies declared as :provided
?
I tend to make deps that are not strictly needed for the library to be usable provided.
An example would be in clj-http that cheshire is not strictly needed, unless you want to do json parsing
Sometimes people make these part of the test / dev dependencies. I think provided is the intended use for this.
nice thanks, I'm trying to add a library to a project now, and I get a million conflicts like
[io.confluent/kafka-schema-registry "5.1.0" :exclusions [org.slf4j/slf4j-log4j12]] -> [io.confluent/rest-utils "5.1.0"] -> [org.eclipse.jetty.websocket/javax-websocket-server-impl "9.4.12.v20180830"] -> [org.eclipse.jetty.websocket/javax-websocket-client-impl "9.4.12.v20180830"] -> [org.eclipse.jetty.websocket/websocket-client "9.4.12.v20180830"] -> [org.eclipse.jetty/jetty-client "9.4.12.v20180830"] -> [org.eclipse.jetty/jetty-http "9.4.12.v20180830"]
the actual version numbers from the main project will however still take precedence right?
would be nice to just exclude everything for that library
e.g. if your main project says clojure 1.10, but a lib says clojure 1.9, you will get 1.10
When deps A and B bring along distinct versions of C it's not too hard to exclude C from one or the other or to state a direct dependency on one particular version of C. The problem is, what happens later?! When updating A or B, will you notice the extraordinary measures, back them out, and reintroduce only if necessary? Or will your project stay forever pinned to C-version-1 long after A and B have moved on to C-version-6?
A deps-resolver syntax that makes clear both the problem and the solution, and applies the solution only when circumstances match the stated problem, would allow tidier engineering
yeah it's a fun problem in every ecosystem really
btw is there a library to generate a graph of the dependencies (with graphviz) that works?
vizdeps seems to be the best one but it's not working anymore, and I could not really find one that works apart from that
Often wondered if (at least on the JVM), it would be possible to isolate all this stuff with some classloader magic. One CL for each dep and a CL graph that mirrored the dependency graph etc. There's a fun project for somebody who gets bored.
@wesley.hall Maybe boot is already doing this with pods
Hi! How can you match all routes with a specific prefix in Bidi? e.g. match all routes that start with /app
. So all routes of the form /app/*/*...
nevermind, the answer was true
(https://github.com/juxt/bidi/blob/master/README.md#catch-all-routes)
I am trying to implement clojure.lang.ILookup
in a record like this
(defrecord StaticMapService [m]
sim/Service
(start_service [this process] this)
(finalize_service [this process] this)
IFn
(invoke [_ ident]
(get m ident))
ILookup
(valAt [_ k] (get m k))
(valAt [_ k not-found] (get m k not-found)))
and I get a Duplicate interface name "clojure/lang/ILookup" in class file compile__stub/services/entityid_service/StaticMapService
error
can't for the life of me see what I am doing wrong
Any suggestions?my guess: defrecord already impls that interface. so you have to use the lower-level deftype
or such
ah of course
Thanks very much
Records already implement ILookup
If you want custom lookup behavior you need to drop down to deftype
oh so I can just merge upon start_service
thankyou
Yes, should be able to
Is there a nice clojure lib to go back and forth between UUIDs and base62-encoded (or similar) UUIDs? (to put in URLs)
There’s the built-in murmurhash (https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/Murmur3.java) - not sure if it would fit the requirements
I would consider that an implementation detail of Clojure and not something to rely on calling into
i have something not quite understood while reading Clojure Programming
(it's really a great book)
it explain one of the usage of recur
is when performing mathematical operation.
> In addition, because it allows you to work with numerics without the overhead of boxed representations, ...
what overhead of boxed representations means?
ah, it was a java stuff
Hey guys!
In clojure jdbc, I am trying to understand :return-keys
How can I get only [{:a … :b ...} ...]
returned?:
(db-do-prepared-return-keys
db
(into statement updates)
{:multi? true
:return-keys {:columns [:a :b]}})
just checking, this is clojure.java.jdbc not clojure.jdbc right? - the name of the latter makes this unfortunately ambiguous
(in fact I think the naming is downright hostile)
yes clojure.java.jdbc
sorry
np - I don't expect most people to know clojure.jdbc exists (I certainly don't recommend using it) - just checking in case there's been miscommunication ;D
:return-keys [:a :b]
didn’t work for me either
I don't think :return-keys is actually an option you can set on db-do-prepared-return-keys
db-do-prepared-return-keys calls prepare-statement with return-keys set to the boolean true, regardless of any options passed in
the prepare-statement docstring has a blurb about the behavior being driver dependent
ok, thanks
ok, I can do :row-fn #(select-keys % [:a :b])
though
interesting
@leontalbot It looks like you only want to select specific columns. In that case you should do that in your SQL statement (instead of SELECT * FROM
do SELECT a,b FROM ...
). The purpose of :return-keys is to get keys generated by inserts from the DB.
@jkr.sw my statement is an UPDATE
one though
@leontalbot :return-keys
can accept a vector of column names on some (but not all) databases. You should not use db-do-prepared-return-keys
really -- it's very low-level (and, I think, assumes you already have a PreparedStatement
-- where you would have set those options prior to calling it!).
insert!
and execute!
should accept :return-keys
with a vector (if your DB allows it).
Also, there's always #sql for deeper clojure.java.jdbc
questions (I'm more likely to see it there).
ok changing channel
@hmaurer I use a very nice library by @tonsky that produces compact 26-char UUIDs: https://github.com/tonsky/compact-uuids
i thought i remembered ghadi making or showing off someone else's uuid -> words library? does that ring a bell with anyone
ill post a gist of that, https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki is the spec
If I wanted to hook into an existing protocol on a built-in type to provide some additional functionality, is there a better way than wrapping the protocol's method I want to extend?
well, there are no protocols or methods there
(there are protocols and methods in the implementation of the object passed to swap!, and swap! itself is an object extending IFn but I don't think that's what you mean)
but if you mean generally, you want to do an AOP style wrapping of an existing function, yeah that's what it typically looks like
though idiomatically wrap-foo
means "hand this thing a function, it returns a new one", which isn't your semantics here, but that's a naming issue
poor choice of nomenclature on my part... I basically just mean if I have a type that implements a protocol, and I want to do something extra with one or all of the functions implementing the protocol on that type, is that the best way
I don’t think protocols have anything to do with your question?
@markw once again that's not a method
method and function aren't interchangeable in Clojure, they mean specific things and we use both
i didn't literally mean method, sorry... "passthrough methods" is just naming convention for functions (or methods in other languages) that do nothing but delegate to another function
sure, most AOP style wrappers will take the original function and then use apply with a variable arg list like in your code
more commonly the function itself is passed as one of the args, which makes the wrapper more reusable (one reason functions are more flexible than methods)
@markw this is also visible in the signature of swap!
itself, and alter-var-root
- the function signatures make it easy to pass in a function that exists already, and return an "enhanced" version
oh, and I don't know why a
is in your function signature there - it's valid to call swap! with a single arg function, and your definition makes that impossible
Hi! Is there a clever way to convert this {:sku [111111111 22222222], :storeId 88888888}
to this {:sku 111111111 :storeId 88888888}, {:sku 22222222 :storeId 88888888}
?
I am not sure about your expected result type. Perhaps you can use ((fn [m] (map #(assoc m :sku %1) (:sku m))) {:sku [111111111 22222222], :storeId 88888888}).
((fn [m] (map #(hash-map :sku %1 :storeId %2) (:sku m) (repeat (:storeId m)))) {:sku [111111111 22222222], :storeId 88888888})
A general version (couldn't think of a good name for the function, gave it my best shot)
(defn explode-key [m explode-key anchor-key] (reduce #(conj %1 {explode-key %2 anchor-key (get m anchor-key)}) [] (get m explode-key))) (explode-key {:sku [111111111 22222222], :storeId 88888888} :sku :storeId)
(defn add-store-id-to-skus [{:keys [sku storeId]}]
(map #(hash-map :sku %, :storeId storeId) sku))
@alexmiller Stepped away for a minute... you're right I guess the question is less about protocols and more about conrete implementations. Maybe an example would be better than me fumbling around with incorrect terminology: If I have a single-function protocol implemented concretely by several different objects, and I want to inject some minor changes to one of the implementations (and don't have access to the code to modify it directly), is wrapping the way i've described generally the best way to go about that? From an OO perspective, I would just subclass and then override the method of interest, do whatever extra stuff I needed to do, and then call the parent's overriden method from the child.
again, I don’t think the fact that this is a protocol function makes any difference
if there is a function, and you want stuff to happen before that call, wrap it in another function
@alexmiller, why do you specifically call out macros with asterisks? I thought the asterisk was just a way to name a variant of a function, like X and X prime, without any conventional meaning. But what you said makes me think there is a convention.
Oh, maybe you meant with exceptions.
Yes, I just meant there were exceptions in the case of macros as you can’t use them as higher order functions
So the abstraction leaks
Clojure intentionally abstracts invocation over functions, multimethods, protocol methods, macros (with asterisks), collections that are invokable, etc so that callers don’t know or care
in general in the core team we take it as a rule of thumb these days to wrap all protocol function invocations in an outer function that gives you a hook to handle special cases
for example, clojure.datafy/datafy is a wrapper function that calls clojure.core.protocols/datafy
if you want something that swaps atoms differently, you can wrap swap! to get a new function, if you want a new thing that swaps differently than an atom you can implement IAtom, and that implementation could even be done compositionally by allocating and using an atom internally
but good usable clojure code tends to wrap functions when possible, rather than extending protocols