Homepage / Notes / Computer Science / Programming Languages / Clojure
A Lisp on the JVM
(print)
to print for humans(println)
to print with newline for humans(pr)
to print for data(prn)
to print with newline for data+ 1 1) (
2
range 5) (
(0 1 2 3 4)
range 5 10) (
(5 6 7 8 9)
range 10 20 2) (
(10 12 14 16 18)
"Damien"
Damien
apply str (reverse "Damien")) (
neimaD
def name "Damien")
(str "Hello " name) (
Hello Damien
", " ["element 1" "element 2" "element 3"]) (clojure.string/join
element 1, element 2, element 3
"Damien" "en") (clojure.string/includes?
true
Clojure characters are Java characters
\a
special character | result |
---|---|
\newline | "\n" |
\space | " " |
\tab | "\t" |
\formfeed | "\f" |
\backspace | "\b" |
\return | "\r" |
Keywords are symbolic identifiers that evaluate to themselves.
Example:
:foo
keyword 'foo) (
:foo
keyword "foo") (
:foo
keyword? :foo) (
true
keyword? "foo") (
false
def x 42)
( x
42
defonce
defonce
defines variable only if it has never been defined before:
defonce y 9)
( y
9
If you try to re-define it, it won't work:
defonce y 10)
( y
9
let [[a b c] '(1 2 3)] (println a b c)) (
1 2 3
Check if something is nil
:
nil? nil) (
true
Check if something is NOT nil
:
nil) (some?
false
1) (some?
let
can be used to define a variable in a specific scope:
let [z 5] z) (
5
z
is not defined outside of the scope:
z
class clojure.lang.Compiler$CompilerException
"defn" = "def" + "fn" (define function)
defn greet [name] (str "Hello, " name))
("Damien") (greet
Hello, Damien
Which is syntactic sugar for:
def greet (fn [name] (str "Hello, " name)))
("Damien") (greet
Hello, Damien
defn greet
("World!"))
([] (greet name] (str "Hello, " name)))
([
println (greet "Damien"))
(println (greet)) (
Hello, Damien
Hello, World!
#()
with %
used as arguments (%1
, %2
for first and second arguments)
map #(* 2 %) '(1 2 3)) (
(2 4 6)
Which is syntactic sugar for:
map (fn [x] (* 2 x)) '(1 2 3)) (
(2 4 6)
All Clojure collections are immutable and persistent.
1 2 3) '(
(1 2 3)
Which is syntactic sugar for:
list 1 2 3) (
(1 2 3)
first '(1 2 3)) (
1
last '(1 2 3)) (
3
count '(1 2 3)) (
3
take 2 '(1 2 3 4)) (
(1 2)
Take Last
take-last 2 '(1 2 3 4)) (
(3 4)
some #(= 3 %) '(1 2 3)) (
true
(some)
alone only returns nil
, not false
some #(= 4 %) '(1 2 3))) (some? (
false
frequencies '("a" "b" "b" "c" "c" "c")) (
{"a" 1, "b" 2, "c" 3}
sort '(2 3 1)) (
(1 2 3)
remove #{"the" "a" "ate"} '("the" "monkey" "ate" "a" "banana")) (
("monkey" "banana")
1 2 3] [
[1 2 3]
Which is syntactic sugar for:
vector 1 2 3) (
[1 2 3]
Collections of unique
values.
1 2 3} #{
#{1 3 2}
Which is syntactic sugar for:
set [1 2 3]) (
#{1 3 2}
Can be used to remove duplicates from a vector:
set [1 2 3 1 2 3]) (
#{1 3 2}
:a 1, :b 2} {
{:a 1, :b 2}
Which is syntactic sugar for:
hash-map :a 1, :b 2) (
{:b 2, :a 1}
Comma is actually not required:
:a 1 :b 2} {
{:a 1, :b 2}
get {:a 1 :b 2} :a) (
1
"get" can be omitted
:a 1 :b 2} :b) ({
2
get-in {:error {:code 404 :message "Wrong location"}} [:error :code]) (
404
if true "this is true" "this is false") (
this is true
if false "this is true" "this is false") (
this is false
Only handles "true", and wrapped in an implicit (do)
statement
when true (println "this is true") (println "this is also true")) (
this is true
this is also true
def x 10)
(cond (= x 10) "true") (
true
Note: for this type of conds, if the first is true, it won't continue
def x (rand-int 50))
(cond
(> x 40) "more than 40"
(> x 30) "more than 30"
(> x 20) "more than 20"
(> x 10) "more than 10"
(:else "neither")
more than 30
Another example
def x (rand-int 50))
(cond
(> x 40) "more than 40"
(> x 30) "more than 30"
(> x 20) "more than 20"
(> x 10) "more than 10"
(:else "neither")
neither
let [name "Damien"]
(case name
("Damien" "my real name"
"Jane" "my neighbour's name"
"John" "my colleague's name"))
my real name
let [name "Jane"]
(case name
("Damien" "my real name"
"Jane" "my neighbour's name"
"John" "my colleague's name"))
my neighbour's name
Can provide a default:
let [name "Hugo"]
(case name
("Damien" "my real name"
"Jane" "my neighbour's name"
"John" "my colleague's name"
"Unknown name"))
Unknown name
Can "match" multiple values using a list:
let [name "Jane"]
(case name
("Damien" "Jane" "John") "an acquaintance"
("not an acquaitance"))
an acquaintance
map #(* 3 %) '(1 2 3)) (
(3 6 9)
reduce + '(3 3 3)) (
9
filter odd? (range 10)) (
(1 3 5 7 9)
equality
of the data.meta #'+)) (pprint (
{:added "1.2",
:ns #namespace[clojure.core],
:name +,
:file "clojure/core.clj",
:inline-arities #function[clojure.core/>1?],
:column 1,
:line 986,
:arglists ([] [x] [x y] [x y & more]),
:doc
"Returns the sum of nums. (+) returns 0. Does not auto-promote\n longs, will throw on overflow. See also: +'",
:inline #function[clojure.core/nary-inline/fn--5606]}
def m ^:hi [1 2 3])
(meta (with-meta m {:bye true})) (
{:bye true}
require '[clojure.string :as str]) (
"a b c") #" ") (str/split (str/upper-case
["A" "B" "C"]
Becomes
-> "a b c" (str/upper-case) (str/split #" ")) (
["A" "B" "C"]
Insert as last argument
->> (range 10) (filter odd?)) (
(1 3 5 7 9)
Write to file:
"blob.txt" "toast") (spit
nil
Read from file:
slurp "blob.txt") (
toast
Can be used over HTTP:
slurp "https://dummyjson.com/quotes/1") (
{"id":1,"quote":"Life isn’t about getting and having, it’s about giving and being.","author":"Kevin Kruse"}
https://lwhorton.github.io/2018/10/20/clojurescript-interop-with-javascript.html
https://google.github.io/closure-library/api/
https://github.com/babashka/nbb
Babahska for ClojureScript / Node.js
https://github.com/babashka/scittle
The Small Clojure Interpreter exposed for usage in browser script tags
https://github.com/thheller/shadow-cljs
ClojureScript compilation made easy
https://github.com/clj-commons/secretary
A client-side router for ClojureScript
https://github.com/squint-cljs/cherry
Experimental ClojureScript to ES6 module compiler
https://github.com/squint-cljs/squint
ClojureScript syntax to JavaScript compiler
https://www.youtube.com/playlist?list=PLUGfdBfjve9VGzp7G1C9FYfH8Yk1Px-11
https://github.com/babashka/babashka
Native, fast starting Clojure interpreter for scripting
https://github.com/clj-kondo/clj-kondo
A linter for Clojure code that sparks joy.
The Fullest Full Stack Clojure Web Framework
https://github.com/weavejester/hiccup
Fast library for rendering HTML in Clojure
https://github.com/Tensegritics/ClojureDart
A port of Clojure that compiles to Dart (mostly for Flutter framework)
https://github.com/tonsky/datascript
Immutable database and Datalog query engine for Clojure, ClojureScript and JS
https://github.com/borkdude/quickdoc
Quick and minimal API doc generation for Clojure
Pedestal is a set of libraries that we use to build services and applications. It runs in the back end and can serve up whole HTML pages or handle API requests.
https://github.com/djblue/portal
A clojure tool to navigate through your data.
Automate Clojure projects without setting your hair on fire.
https://github.com/babashka/neil
A CLI to add common aliases and features to deps.edn-based projects.
https://github.com/vouch-opensource/krell
Simple ClojureScript React Native Tooling
https://github.com/HumbleUI/HumbleUI
Clojure Desktop UI framework
https://kimh.github.io/clojure-by-example/
https://lambdaisland.com/episodes/list-comprehension-clojure-for
https://lambdaisland.com/episodes/clojure-seq-seqable
https://lambdaisland.com/episodes/javascript-libraries-clojurescript
https://lambdaisland.com/episodes/clojure-keyword-arguments
https://lambdaisland.com/episodes/clojurescript-interop