Literate Programmingλ︎
Literate programming is a document written in a natural language, interspersed with snippets of code that can be executed and results visualised as text or graphics. It is an interactive document that can update sections of itself from the code that runs inside.
In Spacemacs and Clojure development, it means you could write a document explaining your project or library and include code that can execute and give results in the document itself.
To encourage contributors to open source project or on-boarding a developer onto a team, a literate programming document that explains how all the important aspects work, including real code examples that they can experiment with, would remove barriers in becoming familiar with a project.
Literate programming with Spacemacsλ︎
Emacs has Org-mode with can do amazing things with documents, simply open a file with a .org
filename extension.
Org-mode includes Babel, which can take code and run it in an Emacs buffer of the correct major-mode for the programming language and automatically return the result back to the org-mode file.
Configure Literate Programming with Clojureλ︎
Add org
and clojure
layers in Spacemacs configuration file
Create a Clojure projectλ︎
Literate programming can be used with any working Clojure project, using either a deps.edn
configuration or a Leiningen project.clj
file.
Create a project using either Clojure CLI tools or Leiningen. Dependencies, apart from Clojure, itself are not required.
Simple example project
Clone practicalli/literate-programming-in-clojure project for a simple example project that works.
Run a Clojure REPLλ︎
Open the deps.edn
, project.clj
, or any source code file from the project.
, m s and select cider-jack-in-clj
to start a REPL.
Create an org file with Clojure code blocksλ︎
Create an org file, eg. literate-clojure.org
in the root of the Clojure project.
Write the text of the document and use , b d
to add a code block, selecting clojure
as the language.
Add :results value
after clojure
in the code block BEGIN
line.
In the code block write your clojure code, e.g. (+ 1 2 3)
Ctrl+C+Ctrl+c to evaluate the code block at the cursor point. The result is pasted underneath the code block.
Clojure Literate programming examplesλ︎
Starting with a very basic Clojure expression to test evaluation is working correctly. Using :results silent
will not add the result to the .org
file.
Ctrl+C+Ctrl+c with the cursor placed in the code block
This should evaluate the Clojure form and echo the results: "5" in the mini-buffer.
Now insert the results into the org buffer immediately after the Clojure code block
Ctrl+C+Ctrl+c with the cursor placed in the code block
The following results block will be inserted immediately following the code block
Multiple expressions can be defined. First define a Clojure data structure (hash-map) and then use a keyword as a function to retrieve a specific value from the hash-map.
#+begin_src clojure :results value
(def small-map {:a 2 :b 4 :c 8})
(:b small-map)
#+end_src
#+RESULTS:
: 4
Make a Graph of the results
Using the Clojure Incanter library to create a line plot graph using the Incanter xy-plot function.
The Incanter library should first be added to the Clojure project as a dependency.
Add Incanter to the :deps
key of the deps.edn
file
Add Incanter to the :dependencies
key of the project.clj
file
Use the Incanter library to create an x-y line plot. The view
function displays the line plot. The plot is also saved to both PDF and PNG format image files.
#+begin_src clojure
(use '(incanter core charts pdf))
;;; Create the x and y data:
(def x-data [0.0 1.0 2.0 3.0 4.0 5.0])
(def y-data [2.3 9.0 2.6 3.1 8.1 4.5])
(def xy-line (xy-plot x-data y-data))
(view xy-line)
(save-pdf xy-line "incanter-xy-line.pdf")
(save xy-line "incanter-xy-line.png")
#+end_src
Insert the image into the exported PDF document:
Files are saved to the root of the Clojure project.
Export to LaTeX or HTMLλ︎
Ctrl+C+Ctrl+e l l to export to LaTeX.
Ctrl+C+Ctrl+e h h to export to HTML.
The exported HTML code will hyperlink the PDF file. To embed the image in the HTML, switch to the PNG image file.
The exported LaTeX (.tex) file will embed either the PDF or PNG file. Graphical quality will be superior with the PDF file.
Session Evaluationλ︎
Use the :session
option to run all Clojure code in the same REPL process
Without :session
each individual code block will execute by starting a Clojure REPL process. Due to the start-up time of a Java virtual machine, this can make execution of many blocks slow.
Sessions changed in Org 9
The :session
option may not be required in Org version 9. Testing is required.
Specify a namespaceλ︎
Each code block will execute in the default user
namespace, unless changed via CIDER nREPL connection.
A namespace can be specified in a code block using the Clojure ns
function.
#+begin_src clojure :results pp
(ns practicalli.greet)
(def hello "Hello Practicalli, this is the greet namespace")
#+end_src
#+RESULTS:
: #'practically.greet/hello
Following code blocks in the .org file will continue to use the specified namespace.