Fipp is a better pretty printer for Clojure.
Like clojure.pprint, this pretty printer has a linear runtime and uses bounded space. However, unlike clojure.pprint, Fipp's implementation is tuned for great performance, functionally pure, and has a data-driven API.
The data interface is agnostic to the source language. Printers are included for Edn data and Clojure code, but it is easy to create a pretty printer for your own language or documents: Even if they're not made out of Clojure data!
Fipp is great for printing large data files and debugging macros, but it is not suitable as a code reformatting tool. (explaination)
Fipp artifacts are published on Clojars.
To depend on this version with Lein, add the following to your project.clj
:
[fipp "0.5.2"]
Puget uses Fipp's engine to provide an alternative, colorizing printer.
Whidbey integrates Puget in to nREPL via Leinigen, so that every evaluation pretty prints in color.
;; Refer with a rename to avoid collision with your REPL's pprint.
(require '[fipp.edn :refer (pprint) :rename {pprint fipp}])
(fipp [1 2 3])
(fipp (range 50))
(fipp (range 20))
(fipp (range 20) {:width 10})
(require '[fipp.clojure])
(fipp.clojure/pprint '(let [foo "abc 123"
bar {:x 1 :y 2 :z 3}]
(do-stuff foo (assoc bar :w 4)))
{:width 40})
The available options are:
:width
defaults to70
.:print-meta
defaults toclojure.core/*print-meta*
.
Any other supported/hidden options are subject to change.
In my non-scientific testing, it has proven to be at least five times as fast
as clojure.pprint
. It also has the nice property of printing no later than
having consumed the bounded amount of memory, so you see your first few lines
of output instantaneously.
The core algorithm is described by Swierstra and Chitil in Linear, Bounded, Functional Pretty-Printing.
Swierstra and Chitil's implementation uses lazy evaluation and requires tying the knot to interleave the measuring and printing phases to achieve the bounded space goal.
However, this implementation is instead a port of the strict evaluation strategy as described by Kiselyov, Peyton-Jones, and Sabry in Lazy v. Yield: Incremental, Linear Pretty-printing.
Clojure's Reducers framework is used to simulate generators and their yield
operator. Unlike lazy reduction, reducers interleave execution of multi-phase
reductions by composition of reducer functions. This enables preservation of
the bounded-space requirement and eases reasoning about the program's behavior.
Clojure's included pretty printer supports pluggable dispatch tables and
provides an API for controlling the printing process. The programming model
is side-effectual. For example, to print a breaking newline, you execute
(pprint-newline :linear)
. This means that it's a difficult and tricky
process to write or compose new pretty printers.
Fipp, on the other hand, accepts a "pretty print document" as input. This document is similar to HTML markup using hiccup.
Here are some examples:
(require '[fipp.printer :refer (pprint-document)])
(defn ppd [doc]
(pprint-document doc {:width 10}))
(ppd [:span "One" :line "Two" :line "Three"])
(ppd [:group "(do" [:nest 2 :line "(step-1)" :line "(step-2)"] ")"])
If you want to write your own printer, see doc/primitives.md for details.
Copyright © 2013 Brandon Bloom
Distributed under the Eclipse Public License, the same as Clojure.
Fipp is fast in part thanks to YourKit's Java Profiler.