Skip to content

Instantly share code, notes, and snippets.

didibus /
Last active January 31, 2023 19:13
When is Clojure "the right tool for the job"?

My answer to: which asked to know when and at what is Clojure "the right tool for the job"?

My take is that in general, the right tool for the job actually doesn't matter that much when it comes to programming language.

There are only a few cases where the options of tools that can do a sufficiently good job at the task become limited.

That's why they are called: General-purpose programming languages, because they can be used generally for most use cases without issues.

Let's look at some of the dimensions that make a difference and what I think of Clojure for them:

didibus / #datafy-nav-example
Last active January 5, 2023 05:09
Clojure datafy/nav example
View #datafy-nav-example
didibus / user.clj
Created January 29, 2020 04:20
A Clojure user.clj file which lets you lazy load certain namespace at the REPL
View user.clj
(def safe-requires
"List of namespaces to require and refer when inside user ns at load time.
Can be given an initialization body to execute after having been required.
To do so, wrap the lib spec in a vector, and all elements after the lib
spec vector will be evaled after the lib spec has been required."
'[[clojure.repl :as repl :refer (source apropos dir pst doc find-doc)]
[ :as javadoc :refer (javadoc)]
[clojure.pprint :as pprint :refer (pp pprint)]
[clojure.stacktrace :as stacktrace :refer (e)]
didibus / JVM clojure command line args to run with low memory
Last active May 10, 2022 22:05
JVM clojure command line args to run with low memory footprint
View JVM clojure command line args to run with low memory

If you want to minimimze the memory overhead of the running JVM, as well as make it so the consumed heap size stays as close to the actual ammount of consumed heap from your app, I've found running with the following args to work best:

clojure -J-XX:+UseSerialGC -J-Xmx256m -J-Xms1m -J-Xss256k -J-XX:MaxHeapFreeRatio=10 -J-XX:MinHeapFreeRatio=1 -J-XX:-ShrinkHeapInSteps -J-X
  • SerialGC has the least memory overhead of all GCs, in that it itself doesn't require a lot of memory to run.
  • SerialGC is also good at quickly releasing Heap memory back to the OS if you configure it as such.
  • TieredStopAtLevel=1 will disable C2 compilation, this used to be called -client option in older JDKs, it won't run as fast due to less optimized compilation, but it needs a lot less memory.
didibus / $
Last active October 26, 2021 05:45
Clojure vs GoLang benchmark - 500 HTTP GET requests
View $

Clojure vs GoLang benchmark - Making 500 HTTP GET requests concurently


In this Gist I wanted to test how quickly Clojure performs 500 HTTP GET requests compared to GO. Surprisingly, using the http-kit Clojure library, a high-performance HTTP client/server implemented in Clojure(and some Java), in turned out that Clojure was faster at fetching 500 times concurently.

I chose http-kit because it is a popular Clojure http client/server, and I did not want to test using

didibus / complex_business_process_example.clj
Last active October 25, 2021 06:58
Example of a complex business process to implement in Clojure. Please link to your solutions for alternative ways to implement the same in Clojure (or other languages).
View complex_business_process_example.clj
(ns complex-business-process-example
"A stupid example of a more complex business process to implement as a flowchart.")
;;;; Config
(def config
"When set to :test will trigger the not-boosted branch which won't write to db.
When set to :prod will trigger the boosted branch which will try to write to the db."
{:env :prod})
didibus / custom_function_creating_tagged_literals.clj
Last active January 5, 2021 22:55
Some Clojure tagged literals to help create functions in various ways, such as create a function that discards any argument passed to it.
View custom_function_creating_tagged_literals.clj
;; This one will create a function that takes 0 or more args and discards them all (doesn't use them).
(defn &-tag-reader
[[f & args]]
`(fn [~'& ~'args] (~f ~@args)))
(set! *data-readers* (assoc *data-readers* '& user/&-tag-reader))
(mapv #&(rand-int 5) (range 10))
;;=> [3 0 4 0 2 0 4 4 4 2]
didibus / control_pmap_concurrency_level_with_rechunking.clj
Last active January 5, 2021 06:32
Example to control Clojure pmap concurrency level using the chunk size of lazy-seqs.
View control_pmap_concurrency_level_with_rechunking.clj
;; From:
(defn re-chunk [n xs]
(when-let [s (seq (take n xs))]
(let [cb (chunk-buffer n)]
(doseq [x s] (chunk-append cb x))
(chunk-cons (chunk cb) (re-chunk n (drop n xs)))))))
;; Simply wrap the collection or seq/lazy-seq with re-chunk and the configured chunk size will make pmap's concurrency level grow to the size of the chunk.
(time (dorun (pmap (fn[e] (Thread/sleep 100) (inc e)) (re-chunk 100 (range 1000)))))
didibus / agent_concurrently_filter_api_call.clj
Created January 5, 2021 05:26
Use Clojure agents to concurrently filter out elements from a collection which requires calling a remote API to know if the element should be filtered or not.
View agent_concurrently_filter_api_call.clj
(defn api-pred [e]
(Thread/sleep 100)
(even? e))
(let [coll-to-process (range 1000)
concurrency 100
agents (repeatedly concurrency #(agent []))]
(doseq [[i agnt] (map vector coll-to-process (cycle agents))]
(send-off agnt
#(if (api-pred i)
didibus / #clojurescript-counter
Last active October 30, 2020 00:31
Example of a simple ClojureScript implementation of a counter, using no dependencies.
View #clojurescript-counter