clojure.set/map-invert
is useful when using a hash map as a dictionary and wish to translate in both directions, e.g. encode/decode.
for
is often used to generate hiccup for web pages, avoiding a lot of repetitive code.
cycle
and rand-nth
to generate repeating sequences and random selection, e.g for creating a carousel of video thumbnails on the London Clojurians website.
I've been using a lot of conditional functions recently, and
or
if
when cond
Also using :`clojure-keywords` and {:hash "maps"}
as functions to extract data. Hopefully those are fairly well known though š
Hi guys, I built a defprotocol implemented in many defrecord. Here an oversimplified version:
(defprotocol A
(foo [_ b])
(bar [_ b]))
(defrecord R1 []
A
(foo [_ b]
(- b 10))
(bar [_ b]
(+ b 10)))
(defrecord R2 []
A
(foo [_ b]
(* b 10))
(bar [_ b]
(/ b 10)))
I don't find a smart way to carry the same tests (= a (-> a (.foo) (.bar)))
on all implementations without copying some boilerplate for R1, R2, R3, ... Is there any way to factorize?Right now, I have to copy my tests on all deftest for every defrecord...
Wrap the tests in a function that takes the record as arg?
Hmm, fair enough. Some "utility test functions" including testing sentences.
Also checkout https://clojuredocs.org/clojure.test/are
(are [a] (= a (-> a foo bar))
r1
r2)
Actually this is what are
is for, my bad for not recommending it at the start
FYI you should not use Java interop to invoke protocol methods on a record, you should invoke the protocol method
Idiomatic question, is this proper clojure idiom to use for updating a data structure based on an expensive calculation?
It's convenient to use let to store a series of intermediate results that depend on previous let values. I'm not sure if that is expected practice.
(defn buncha-calcs
"returns processed-data with a-data and b-data data structure fields updated"
[processed-data input-data]
(let [stage-1 (expensive-calc input-data)
a-results (calc-a (:a-data processed-data) stage-1 )
b-results (calc-a (:b-data processed-data) stage-1 )
]
(assoc
(assoc processed-data :a-data a-results )
:b-data b-results)))
> It's convenient to use let to store a series of intermediate results that depend on previous let values. I'm not sure if that is expected practice.
That's exactly what let
is meant for.
assoc
can take multiple key-values, which means, you can do this with one call to assoc
, like this:
(defn buncha-calcs
"returns processed-data with a-data and b-data data structure fields updated"
[processed input]
(let [stage-1 (expensive-calc input)
a-results (calc-a (:a-data processed) stage-1)
b-results (calc-a (:b-data processed) stage-1)]
(assoc processed :a-data a-results :b-data b-results)))
I also removed the -data
suffix from the arg-names. Because Clojure is a very data-centric language, IMO it's reasonable to assume something is data unless mentioned otherwise. This is a personal opinion though.
Now, you are effectively applying the function calc-a
to the values of two keys, along with an extra argument. update
does this more directly as opposed to manually getting the value, applying the function, and assoc
iating it back-in. Looks like this:
(defn buncha-calcs
"returns processed-data with a-data and b-data data structure fields updated"
[processed input]
(let [stage-1 (expensive-calc input)]
(update
(update processed :a-data calc-a stage-1)
:b-data calc-b stage-1)))
Finally, operations like assoc
, dissoc
, conj
and update
are collection-level functions (take a collection as their first arg and return a collection), and compose well with the thread-first macro (`->`), which when used the code becomes more linear to read:
(defn buncha-calcs
"returns processed-data with a-data and b-data data structure fields updated"
[processed input]
(let [stage-1 (expensive-calc input)]
(-> processed
(update :a-data calc-a stage-1)
(update :b-data calc-a stage-1))))
^ This is the most idiomatic way to write this IMHO.
And if you haven't encountered threading macros before, I highly recommend checking out http://clojure.org/guides/threading_macros.
PS: FYI you can use triple back-ticks to format multiline code-snippets.Hi, Iām having this error when publishing to heroku.
Could not transfer artifact net.sf.saxon:saxon:pom:9 from/to jboss (<https://repository.jboss.org/nexus/content/repositories/deprecated/>): Connection reset
This could be due to a typo in :dependencies, file system permissions, or network issues.
If you are behind a proxy, try setting the 'http_proxy' environment variable.
Uberjar aborting because jar failed: Could not resolve dependencies
My dependencies:
:repositories [["enonic" "<https://repo.enonic.com/public/>"]]
:dependencies [[camel-snake-kebab "0.4.2"]
[clj-http "3.10.1"]
[environ "1.2.0"]
[integrant "0.8.0"]
[integrant/repl "0.3.1"]
[io.xapix/paos "0.2.4"]
[metosin/reitit "0.5.10"]
[org.clojure/clojure "1.10.1"]
[org.postgresql/postgresql "42.2.14"]
[ovotech/ring-jwt "1.3.0"]
[ring "1.8.2"]
[seancorfield/next.jdbc "1.1.613"]
[buddy "2.0.0"]
[clojure.java-time "0.3.2"]
[ring/ring-mock "0.4.0"]
[ring-cors "0.1.13"]]
Does anyone knows how to solve this?Thanks, that is super helpful