HackerReposA FIELD GUIDE TO OPEN SOURCE
ProSponsor the shelf♧ 0
← Back to top all-time
redplanetlabs
specter
Clojure2015–2025
redplanetlabs / specter

specter

Clojure(Script)'s missing piece

30Distinct people
30Mentions
2Explicit recommenders
2.6KGitHub stars
REPOSITORY AT A GLANCE

What to know before exploring

What it is

Clojure(Script)'s missing piece

GitHub

Where it is used

No documented product use was verified in the last source check.

What people are saying

This might have been unintentional, but I suspect "Spectre of Structure" and "Python's missing piece" refer to Nathan Marz's specter library for clojure [1], similarly touted…

hessammehr used a recommendation phrase. 2 indexed comments match. This is a phrase match, not a verdict.

No classified warning is attached to this page. Read the discussions before treating silence as approval.

Also in these discussions

Mentioned in the same Hacker News threads. That is not proof they are substitutes.

This week on Hacker News

Nov 8–Nov 15 UTC · Direct repository links and separately labeled related project stories. Indexed through 11/15/2026, 6:01:32 PM UTC.

No direct repository links were found in the indexed HN discussions over the past seven days. Older discussions are available below.

Mentions over time

HN mentions by year30 dated mentions

Observed mentions: 2015-05-14 16:23:57 UTC to 2025-08-27 17:07:14 UTC.

0123452015-01-01 00:00:00 UTC to 2016-01-01 00:00:00 UTC (exclusive): 5 mentions; 2 submissions, 3 comments20152016-01-01 00:00:00 UTC to 2017-01-01 00:00:00 UTC (exclusive): 2 mentions; 0 submissions, 2 comments2017-01-01 00:00:00 UTC to 2018-01-01 00:00:00 UTC (exclusive): 1 mentions; 0 submissions, 1 comments2018-01-01 00:00:00 UTC to 2019-01-01 00:00:00 UTC (exclusive): 5 mentions; 0 submissions, 5 comments2019-01-01 00:00:00 UTC to 2020-01-01 00:00:00 UTC (exclusive): 3 mentions; 0 submissions, 3 comments2020-01-01 00:00:00 UTC to 2021-01-01 00:00:00 UTC (exclusive): 5 mentions; 0 submissions, 5 comments20202021-01-01 00:00:00 UTC to 2022-01-01 00:00:00 UTC (exclusive): 3 mentions; 1 submissions, 2 comments2022-01-01 00:00:00 UTC to 2023-01-01 00:00:00 UTC (exclusive): 0 mentions; 0 submissions, 0 comments2023-01-01 00:00:00 UTC to 2024-01-01 00:00:00 UTC (exclusive): 1 mentions; 0 submissions, 1 comments2024-01-01 00:00:00 UTC to 2025-01-01 00:00:00 UTC (exclusive): 2 mentions; 0 submissions, 2 comments2025-01-01 00:00:00 UTC to 2026-01-01 00:00:00 UTC (exclusive): 3 mentions; 0 submissions, 3 comments2025

Counts come from the repository’s dated source evidence. Index cutoff: 2026-11-02 08:16:59 UTC.

View mention counts and date ranges
UTC ranges include their start and exclude their end. Select a period to filter the source evidence.
PeriodStart (UTC)End (exclusive, UTC)MentionsSubmissionsComments
20152015-01-01 00:00:00 UTC2016-01-01 00:00:00 UTC523
20162016-01-01 00:00:00 UTC2017-01-01 00:00:00 UTC202
20172017-01-01 00:00:00 UTC2018-01-01 00:00:00 UTC101
20182018-01-01 00:00:00 UTC2019-01-01 00:00:00 UTC505
20192019-01-01 00:00:00 UTC2020-01-01 00:00:00 UTC303
20202020-01-01 00:00:00 UTC2021-01-01 00:00:00 UTC505
20212021-01-01 00:00:00 UTC2022-01-01 00:00:00 UTC312
20222022-01-01 00:00:00 UTC2023-01-01 00:00:00 UTC000
20232023-01-01 00:00:00 UTC2024-01-01 00:00:00 UTC101
20242024-01-01 00:00:00 UTC2025-01-01 00:00:00 UTC202
20252025-01-01 00:00:00 UTC2026-01-01 00:00:00 UTC303

From the project README

An excerpt from the repository, fetched Nov 13, 2026.

Read the project’s introduction
Specter 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). Consider these examples: Example 1: Increment every even number nested within map of vector of maps (def data {:a [{:aa 1 :bb 2} {:cc 3}] :b [{:dd 4}]}) ;; Manual Clojure (defn map-vals [m afn] (->> m (map (fn [[k v]] [k (afn v)])) (into (empty m)))) (map-vals data (fn [v] (mapv (fn [m] (map-vals m (fn [v] (if (even? v) (inc v) v)))) v))) ;; Specter (transform [MAP-VALS ALL MAP-VALS even?] inc data) Example 2: Append a sequence of elements to a nested vector (def data {:a [1 2 3]}) ;; Manual Clojure (update data :a (fn [v] (into (if v v []) [4 5]))) ;; Specter (setval [:a END] [4 5] data) Example 3: Increment the last odd number in a sequence (def data [1 2 3 4 5 6 7 8]) ;; Manual Clojure (let [idx (reduce-kv (fn [res i v] (if (odd? v) i res)) nil data)] (if idx (update data idx inc) data)) ;; Specter (transform [(filterer odd?) LAST] inc data) Example 4: Map a function over a sequence without changing the type or order of the sequence ;; Manual Clojure (map inc data) ;; doesn't work, becomes a lazy sequence (into (empty data) (map inc data)) ;; doesn't work, reverses the order of lists ;; Specter (transform ALL inc data) ;; works for all Clojure datatypes with near-optimal efficiency Latest Version The latest release version of Specter is hosted on Clojars: Learn Specter Introductory blog post: Clojure's missing piece Presentation about Specter: Specter: Powerful and Simple Data Structure Manipulation Note that this presentation was given before Specter's inline compilation/caching system was developed. You no longer need to do anything special to get near-optimal performance. Screencast on Specter: Understanding Specter List of navigators with examples: This wiki page provides a more comprehensive overview than the API docs about the behavior of specific navigators and includes many examples. Core operations and defining new navigators: This wiki page provides a more comprehensive overview than the API docs of the core select/transform/etc. operations and the operations for defining new navigators. This wiki page explains how to do precise and efficient recursive navigation with Specter. This wiki page provides a comprehensive overview of how to use Specter's zipper navigators. Zippers are a much slower navigation method but can perform certain tasks that are not possible with Specter's regular navigators. Note that zippers are rarely needed. Cheat Sheet API docs Performance guide: This post provides an overview of how Specter achieves its performance. Specter's API is contained in these files: specter.cljc: This contains the built-in navigators and the definition of the core operations. transients.cljc: This contains navigators for transient collections. zipper.cljc: This integrates zipper-based navigation into Specter. Questions? You can ask questions about Specter by opening an issue on Github. You can also find help in the #specter channel on Clojurians. Examples Increment all the values in maps of maps: user> (use 'com.rpl.specter) user> (transform [MAP-VALS MAP-VALS] inc {:a {:aa 1} :b {:ba -1 :bb 2}}) {:a {:aa 2}, :b {:ba 0, :bb 3}} Increment all the even values for :a keys in a sequence of maps: user> (transform [ALL :a even?] inc [{:a 1} {:a 2} {:a 4} {:a 3}]) [{:a 1} {:a 3} {:a 5} {:a 3}] Retrieve every number divisible by 3 out of a sequence of sequences: user> (select [ALL ALL #(= 0 (mod % 3))] [[1 2 3 4] [] [5 3 2 18] [2 4 6] [12]]) [3 3 18 6 12] Increment the last odd number in a sequence: user> (transform [(filterer odd?) LAST] inc [2 1 3 6 9 4 8]) [2 1 3 6 10 4 8] Remove nils from a nested sequence: user> (setval [:a ALL nil?] NONE {:a [1 2 nil 3 nil]}) {:a [1 2 3]} Remove key/value pair from nested map: user> (setval [:a :b :c] NONE {:a {:b {:c 1}}}) {:a {:b {}}} Remove key/value pair from nested map, removing maps that become empty along the way: user> (setval [:a (compact :b :c)] NONE {:a {:b {:c 1}}}) {} Increment all the odd numbers between indices 1 (inclusive) and 4 (exclusive): user> (transform [(srange 1 4) ALL odd?] inc [0 1 2
Read the full README on GitHub

What Hacker News says

2 sources

MAKE YOURSELF AT HOME

A few shortcuts

/
Search the collection
?
Open this guide
Esc
Close dialogs and navigation

Your saved repositories and interests stay in this browser.