Specter rejects Clojure's restrictive approach to immutable data structure manipulation, instead exposing an elegant API to allow any sort of manipula

redplanetlabs / specter

submited by
Style Pass
2021-07-03 14:30:09

Specter rejects Clojure's restrictive approach to immutable data structure manipulation, instead exposing an elegant API to allow any sort of manipulation imaginable. Specter especially excels at querying and transforming nested and recursive data, important use cases that are very complex to handle with vanilla Clojure.

Specter has an extremely simple core, just a single abstraction called "navigator". Queries and transforms are done by composing navigators into a "path" precisely targeting what you want to retrieve or change. Navigators can be composed with any other navigators, allowing sophisticated manipulations to be expressed very concisely.

In addition, Specter has performance rivaling hand-optimized code (see this benchmark). Clojure's only comparable built-in operations are get-in and update-in, and the Specter equivalents are 30% and 85% faster respectively (while being just as concise). Under the hood, Specter uses advanced dynamic techniques to strip away the overhead of composition.

There are some key differences between the Clojure approach to data manipulation and the Specter approach. Unlike Clojure, Specter always uses the most efficient method possible to implement an operation for a datatype (e.g. last vs. LAST). Clojure intentionally leaves out many operations, such as prepending to a vector or inserting into the middle of a sequence. Specter has navigators that cover these use cases (BEFORE-ELEM and before-index) and many more. Finally, Specter transforms always target precise parts of a data structure, leaving everything else the same. For instance, ALL targets every value within a sequence, and the resulting transform is always the same type as the input (e.g. a vector stays a vector, a sorted map stays a sorted map).

Leave a Comment
Related Posts