Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/dundalek/clojurescript-guide
My notes on ClojureScript
https://github.com/dundalek/clojurescript-guide
Last synced: about 1 month ago
JSON representation
My notes on ClojureScript
- Host: GitHub
- URL: https://github.com/dundalek/clojurescript-guide
- Owner: dundalek
- Created: 2017-05-15T13:54:53.000Z (over 7 years ago)
- Default Branch: master
- Last Pushed: 2021-09-10T18:56:12.000Z (about 3 years ago)
- Last Synced: 2024-07-21T00:36:05.674Z (about 2 months ago)
- Size: 8.79 KB
- Stars: 69
- Watchers: 5
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# The Missing Guide for ClojureScript
When I started with ClojureScript and tried to follow the official [Quick Start Guide](https://clojurescript.org/guides/quick-start) it did not seem very straightforward to me. It is a good read though after a bit of hands on experience. This guide is a compilation of things I wished to know at the beginnings.
> ⚠ **DISCLAIMER**
> I wrote down these notes as I was learning Clojure/Script in 2017. The tooling ecosystem changed significantly since then, but I did not manage to update the guide to reflect that. Here is the gist:
> * [Clojure CLI](https://clojure.org/guides/deps_and_cli) is a better alternative to Leiningen
> * [shadow-cljs](https://github.com/thheller/shadow-cljs) is the best tool to compile ClojureScript replacing Fighweel, both for web and node.js apps
> * [Babashka](https://github.com/babashka/babashka) is a best runtime for scripting instead of Lumo- [Quick Start](#quick-start)
- [Create a project](#create-a-project)
- [Documentation](#documentation)
- [Resources](#resources)
- [Tutorials](#tutorials)
- [Books](#books)
- [Exercises](#exercises)
- [Cookbook](#cookbook)
- [Libraries](#libraries)
- [JS Interop](#js-interop)
- [IO](#io)
- [EDN](#edn)
- [Editor setup](#editor-setup)
- [Debugging](#debugging)
- [Tools](#tools)
- [Misc](#misc)## Quick Start
Try out some code using REPL.
Under node.js install [Lumo](https://github.com/anmonteiro/lumo) with:
```
$ npm install -g lumo-cljs
$ lumo
cljs.user=> (println "hello clojure")
hello clojure
```For Java first install [Leiningen](https://leiningen.org/) and then:
```
$ lein repl
user=> (+ 1 2)
3
```### Create a project
#### Node.js server or CLI app
Use [cljs-node-app](https://github.com/yanatan16/cljs-node-app-template) template:
`lein new cljs-node-app `Compile the project: `lein cljsbuild once main`
Watch and recompile on changes: `lein cljsbuild auto main`
#### Web app
Use [re-frame](https://github.com/Day8/re-frame-template) template which uses React.js via [Reagent](https://github.com/reagent-project/reagent) under the hood:
`lein new re-frame +test +routes +aliases`Start development mode with live reload: `lein dev`
Compile the project: `lein build`
## Documentation
Inside REPL:
```clojure
;; Show function docs in REPL
(doc str);; Search in docs
(find-doc "reduce");; Show function source code
(source identity)
```Browse [API documentation](https://clojuredocs.org/quickref) and refer to [Cheatsheet](http://clojure.org/cheatsheet) on the web.
## Resources
- [Official Clojure Reference](https://clojure.org/reference/reader)
- [Library Coding Standards](https://dev.clojure.org/display/community/Library+Coding+Standards)
- [Clojure Styleguide](https://github.com/bbatsov/clojure-style-guide)
- [clojure-doc.org](http://clojure-doc.org/articles/content.html) is community-driven documentation
- [Anki deck](https://ankiweb.net/shared/info/3248915342) for spaced-repetition learning### Tutorials
- [Learn Clojure in Y minutes](http://learnxinyminutes.com/docs/clojure/) is a very concise indroduction to Clojure.
- [ClojureScript Unraveled](http://funcool.github.io/clojurescript-unraveled/) is an online book and guide about ClojureScript.
- [Brave Clojure – Chapter 3 Crash Course](http://www.braveclojure.com/do-things/)
Clojure for the Brave and True is a book available online. I find chapter 3 a very good intro to Clojure. If you like more chatty style and humor in programming books then also give a read to other chapters.
- [Clojure – Functional Programming for the JVM](http://java.ociweb.com/mark/clojure/article.html) is an introductory article to functional programming and Clojure. It is aimed for Java programmers but contains interesting bits of information and goes into more low-level details.
- [Clojure from the ground up](https://aphyr.com/tags/Clojure-from-the-ground-up) is a collection of articles on various Clojure topics.### Books
- [Programming Clojure by Stuart Halloway](https://www.amazon.com/dp/1934356867) is a best book about Clojure for programmers, I recommend anyone learning Clojure(Script) to start with this one.
- [Clojure Applied: From Practice to Practitioner](https://www.amazon.com/dp/1680500740) is a book focusing on more practical aspects of app development in Clojure. Includes chapters about domain modelling, managing state and application components.
- [Mastering Clojure](https://www.amazon.com/dp/B017XSFL4Q/) describes in detail more advanced topics like paralelism, transducers, category theory, pattern matching and logic programming.Explore other [books](https://clojure.org/community/books) by the community.
### Exercises
- [99 Lisp Problems](http://www.ic.unicamp.br/~meidanis/courses/mc336/2006s2/funcional/L-99_Ninety-Nine_Lisp_Problems.html)
- [4Clojure](http://www.4clojure.com/problems)
- [Clojure Koans](http://clojurekoans.com/)
- [Project Euler Problems](https://projecteuler.net/archives)
- [Simple Programming Problems](https://adriann.github.io/programming_problems.html)## Cookbook
### Libraries
Opinionated list of useful libraries. There are alternatives but if you are just starting you can't go wrong by picking these.
**Frontend**
- React wrapper framework: [re-frame](https://github.com/Day8/re-frame)
- UI Components: [re-com](https://github.com/Day8/re-com)
- Forms with validation: [Reforms](https://github.com/bilus/reforms)
- HTTP requests: [cljs-ajax](https://github.com/JulianBirch/cljs-ajax)
- Routing: [Secretary](https://github.com/gf3/secretary)
- Date, Url and other utilities: [Google Closure Library](https://google.github.io/closure-library/api/goog.html)Check other libraries in [Awesome ClojureScript list](https://github.com/hantuzun/awesome-clojurescript).
**Backend**
- HTTP APIs: [Compojure](https://github.com/metosin/compojure-api)
- Logging: [Timbre](https://github.com/ptaoussanis/timbre)### JS Interop
A great feature of ClojureScript is that you can work with native JS objects and use existing JS libraries.
```clojure
;; Use js/ prefix for global names, e.g. to print in browser console
(js/console.log "Hello, world!");; Add dot to construct new objects
(js/Date. "2017-10-16") ; new Date("2017-10-16");; Call methods
(.toUpperCase s) ; s.toUpperCase();; Use treading macro to chain calls
(-> "BOOM" (.toLowerCase) (.slice 0 -1)) ; "BOOM".toLowerCase().slice(0, -1);; Access attributes
(.-length s) ; s.length;; Nested attribute access
(.-location.href js/window) ; window.location.href
(aget window "location" "href") ; window["location"]["href"];; Set attributes
(aset obj "attr" "val") ; obj["attr"] = "val";; create native js objects with #js macro
#js {:a 1 :b 2} ; {a: 1, b: 2}
#js [1 2 3] ; [1, 2, 3];; convert cljs data structures into js objects
(clj->js obj);; convert js objects to cljs data structures
(js->clj obj :keywordize-keys true))
```See a [post with more details](http://www.spacjer.com/blog/2014/09/12/clojurescript-javascript-interop/) and [comparison of JS and Clojure](https://kanaka.github.io/clojurescript/web/synonym.html) idioms.
Use node modules by [seamlessly requiring](https://clojurescript.org/news/2017-07-12-clojurescript-is-not-an-island-integrating-node-modules) them (starting with 1.9.854):
```clojure
(ns example.core
(:require [react :refer [createElement]]
["react-dom/server" :as ReactDOMServer :refer [renderToString]]))(js/console.log (renderToString (createElement "div" nil "Hello World!")))
```Some js libraries do not work with the compiler. In that case it is possible to bundle them with [webpack](https://github.com/roman01la/cljs-reagent-webpack).
Or use externs: https://code.thheller.com/blog/shadow-cljs/2017/10/15/externs-the-bane-of-every-release-build.html
Debug advanced compilation errors with [:pseudo-names](https://clojurescript.org/reference/compiler-options#pseudo-names). Also try [:infer-externs](https://clojurescript.org/reference/compiler-options#infer-externs).### IO
To print at ClojureScript REPL
```clojure
(println "Hello, world!")
```Working with filesystem – require `fs` from node and call native functions.
```clojure
(def fs (js/require "fs"))
(fs.readFileSync "foo.txt" "utf8")
```When working in repl you can use `slurp` to read a file and `spit` to write a file.
```clojure
;; Read a file into one long string
(def a-long-string (slurp "foo.txt"));; Write a long string out to a new file
(spit "foo.txt"
"A long
multi-line string.
Bye.")
```Alternative approach is to use [cljs-node-io](https://github.com/pkpkpk/cljs-node-io) which is a port of [clojure.java.io](http://clojure-doc.org/articles/cookbooks/files_and_directories.html).
### EDN
EDN is to Clojure what JSON is to Javascript.
- parse: [cljs.reader/read-string](https://cljs.github.io/api/cljs.reader/read-string)
- stringify: [prn-str](http://cljs.github.io/api/cljs.core/prn-str)### State
A state is the value of an identity at a point in time.
Changes to shared state:
- Refs - coordinated synchronous
- Atoms - uncoordinated synchronous
- Agents - asynchronous
- Vars - thread-local private - def, defnConvention dynamic thread-wide bindings with asterisks `*in*` `*out*`.
## Editor setup
**[Atom](https://atom.io)**
Refer to [this guide](https://gist.github.com/jasongilman/d1f70507bed021b48625) for a good setup. Essential packages are:
- [parinfer](https://atom.io/packages/parinfer) so that you don't have to worry about parentheses
- [proto-repl](https://atom.io/packages/proto-repl) to evaluate code right within editor window**[Spacemacs](http://spacemacs.org/)**
- Emacs distribution with Vim mode
- Looks intriguing, it's on my list of things to try
- Plugin for code refactoring: [clj-refactor](https://github.com/clojure-emacs/clj-refactor.el/wiki)**[Cursive](https://cursive-ide.com/)**
- a great IDE based on IntelliJ## Debugging
**Debug with Chrome DevTools**
- [Enable custom formatters](https://github.com/binaryage/cljs-devtools/blob/master/docs/installation.md#enable-custom-formatters-in-chrome)
- Data formating is done with [cljs-devtools](https://github.com/binaryage/cljs-devtools) which is already included in the [web app template](#web-app) mentioned above
- Add expressions to watches like: `cljs.core.pr_str(localvar)`For more functionality use [Dirac](https://github.com/binaryage/dirac), a DevTools fork with additional ClojureScript related features.
**Debug node apps with Chrome DevTools**
- Run `node --inspect-brk build/main.js`
- In Chrome open `chrome://inspect` and select the session**Call tracing inside Atom**
Use `proto-repl: save call` to record function calls and values of parameters, watch [video with instructions](https://youtu.be/buPPGxOnBnk?t=11m55s).
**General call tracing**
Trace calls with [Clairvoyant](https://github.com/spellhouse/clairvoyant) which is an alternative to [clojure.tools.trace](https://github.com/clojure/tools.trace).
## Tools
To use Leiningen plugins globally across projects put them in `~/.lein/profiles.clj`, e.g.
```clojure
{:user {:plugins [[lein-ancient "0.6.5"]
[lein-plz "0.4.0-SNAPSHOT" :exclusions [[rewrite-clj] [ancient-clj]]]]}}
```[List of Leiningen plugins](https://github.com/technomancy/leiningen/wiki/Plugins)
**Packages management**
- `lein search ` – Search for packages
- `lein plz add ` – Add package as dependency into `project.clj`
- `lein ancient` – List outdated dependencies
- `lein ancient upgrade` – Upgrade outdated dependencies
- [lein try](https://github.com/rkneufeld/lein-try) – Try out Clojure libraries in a REPL without creating a project or adding them to an existing project.**Code quality**
- [kibit](https://github.com/jonase/kibit) – static analysis tool that offers suggestions for code improvement
- [cljfmt](https://github.com/weavejester/cljfmt) or [lein-zprint](https://github.com/kkinnear/lein-zprint) or [boot-fmt](https://github.com/pesterhazy/boot-fmt) for code auto-formatting
- [cloverage](https://github.com/cloverage/cloverage) – Test code coverage tool
- [vanity](https://github.com/dgtized/lein-vanity) - Compute Lines of code statistics
- [Overview of code quality tools](https://blog.jeaye.com/2017/08/31/clojure-code-quality/)**Code exploration**
- [lein-ns-dep-graph](https://github.com/hilverd/lein-ns-dep-graph) or [lein-hiera](https://github.com/greglook/lein-hiera) – Explore and visualize namespace dependencies
- [lein-gossip](https://github.com/actsasgeek/lein-gossip) or [clj-usage-graph](https://github.com/gfredericks/clj-usage-graph) – Visualize call-graphs in a codebase
- [lein-instant-cheatsheet](https://github.com/cammsaul/lein-instant-cheatsheet) – Instant Cheatsheet instantly creates a cheatsheet for your project and its dependencies**Documentation generators**
Recommended:
- [cljdoc](https://cljdoc.xyz/) – documentation generator, includes hosting
- [codeina](https://github.com/funcool/codeina) – api doc generator which is a nicer looking fork of codox
- [codox](https://github.com/weavejester/codox) – with support for plugins and themes
- [codox-md](https://github.com/hugoduncan/codox-md)
- [marginalia](https://github.com/gdeer81/lein-marginalia) – documentation showing description and code side by side in a literate programming styleOthers:
- [autodoc](https://github.com/tomfaulhaber/lein-autodoc) – generator that is used for official Clojure API docs
- [cadastre](https://github.com/dakrone/cadastre) – extracts metadata in a way that is used on [clojuredocs.org](http://clojuredocs.org/)## Misc
[CrossClj](https://crossclj.info/) – Explore dependencies of Clojure packages among each other, see which function are called where and with what arguments:
[JavaScript to ClojureScript translator](https://github.com/roman01la/javascript-to-clojurescript)
Bootstrapping:
- [calvin](https://github.com/eginez/calvin) – A minimalistic build tool for ClojureScript projects that does not require the JVM
- [with Lumo](https://anmonteiro.com/2017/02/compiling-clojurescript-projects-without-the-jvm/)Articles about Lisp and Functional Programming:
- https://gist.github.com/reborg/dc8b0c96c397a56668905e2767fd697f
- http://www.paulgraham.com/icad.html
- https://funcall.blogspot.cz/2009/03/not-lisp-again.html
- http://calculist.org/blog/2012/04/17/homoiconicity-isnt-the-point/
- http://www.michaelnielsen.org/ddi/lisp-as-the-maxwells-equations-of-software/
- http://www.lihaoyi.com/post/WhatsFunctionalProgrammingAllAbout.html
- http://www.cs.umd.edu/~nau/cmsc421/norvig-lisp-style.pdf