### Map a function over a sequence without changing the type or order Source: https://github.com/redplanetlabs/specter/blob/master/README.md This example addresses a common challenge in Clojure: applying a function to all elements of a sequence while preserving its original type and order. It shows how standard `map` and `into` operations can alter the sequence type or order, and how Specter's `ALL` navigator provides a robust and efficient solution for this use case across all Clojure datatypes. ```Clojure ;; 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 ``` ```Clojure ;; Specter (transform ALL inc data) ;; works for all Clojure datatypes with near-optimal efficiency ``` -------------------------------- ### Creating Recursive Paths with `recursive-path` in Clojure Source: https://github.com/redplanetlabs/specter/blob/master/CHANGES.md This example shows how to use `recursive-path` to define a path that can traverse nested data structures, such as a tree. It illustrates a `tree-walker` that navigates vectors, applying the path recursively to their elements. ```clojure (let [tree-walker (recursive-path [] p (if-path vector? [ALL p] STAY))] (select tree-walker [1 [2 [3 4] 5] [[6]]])) ``` -------------------------------- ### Reverse Even Numbers in a Tree using Conditional Navigation (Clojure) Source: https://github.com/redplanetlabs/specter/blob/master/README.md Shows how to reverse the positions of even numbers in a tree using `recursive-path` and `if-path` for conditional navigation. The example demonstrates a depth-first search order and the application of `reverse` via `transform`. ```Clojure (def TreeValues (recursive-path [] p (if-path vector? [ALL p] STAY ))) (transform (subselect TreeValues even?) reverse [1 2 [3 [[4]] 5] [6 [7 8] 9 [[10]]]] ) ;; => [1 10 [3 [[8]] 5] [6 [7 4] 9 [[2]]] ``` -------------------------------- ### Collect Values During Transformation (Clojure Specter) Source: https://github.com/redplanetlabs/specter/blob/master/README.md Explains how Specter allows collecting values during navigation to use in the transform function. `VAL` adds the current element, `collect` finds a sequence of values, and `collect-one` expects a single value. This example uses `collect-one` to add the value of the `:b` key to the `:a` key if `:a` is even. ```Clojure user> (transform [ALL (collect-one :b) :a even?] + [{:a 1 :b 3} {:a 2 :b -10} {:a 4 :b 10} {:a 3}]) [{:b 3, :a 1} {:b -10, :a -8} {:b 10, :a 14} {:a 3}] ``` -------------------------------- ### Append a sequence of elements to a nested vector Source: https://github.com/redplanetlabs/specter/blob/master/README.md This example illustrates how to append a sequence of elements to a vector nested within a map. It highlights the difference in complexity between manual Clojure's `update` with `into` and Specter's direct `setval` using the `END` navigator. ```Clojure (def data {:a [1 2 3]}) ;; Manual Clojure (update data :a (fn [v] (into (if v v []) [4 5]))) ``` ```Clojure ;; Specter (setval [:a END] [4 5] data) ``` -------------------------------- ### Increment Odd Numbers in Sequence Range (Clojure Specter) Source: https://github.com/redplanetlabs/specter/blob/master/README.md Shows how to apply a transformation to odd numbers within a specified index range (inclusive start, exclusive end) using `srange`. ```Clojure user> (transform [(srange 1 4) ALL odd?] inc [0 1 2 3 4 5 6 7]) [0 2 2 4 4 5 6 7] ``` -------------------------------- ### Increment the last odd number in a sequence Source: https://github.com/redplanetlabs/specter/blob/master/README.md This example demonstrates how to locate and increment only the last odd number within a sequence. It contrasts the manual Clojure approach, which requires iterating and tracking the index, with Specter's more declarative and concise path composition using `filterer` and `LAST`. ```Clojure (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)) ``` ```Clojure ;; Specter (transform [(filterer odd?) LAST] inc data) ``` -------------------------------- ### Increment every even number nested within map of vector of maps Source: https://github.com/redplanetlabs/specter/blob/master/README.md This example demonstrates how to increment every even number found within a complex, nested data structure (a map containing a vector of maps). It contrasts the verbose manual Clojure approach with Specter's concise and powerful transformation capabilities. ```Clojure (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))) ``` ```Clojure ;; Specter (transform [MAP-VALS ALL MAP-VALS even?] inc data) ``` -------------------------------- ### Run Clojure Tests with Leiningen Source: https://github.com/redplanetlabs/specter/blob/master/DEVELOPER.md This command executes all Clojure tests in the project. It first cleans the project, then runs the test suite using Leiningen. ```Shell lein do clean, test ``` -------------------------------- ### Run Specific Project Benchmarks Source: https://github.com/redplanetlabs/specter/blob/master/DEVELOPER.md Execute one or more specific benchmarks by providing their names as arguments to the benchmark script. Benchmark names containing spaces should be enclosed in double quotes. ```Shell scripts/run-benchmarks "prepend to a vector" "filter a sequence" ``` -------------------------------- ### Run ClojureScript Tests with Leiningen Doo Source: https://github.com/redplanetlabs/specter/blob/master/DEVELOPER.md This sequence of commands compiles Java code and then runs ClojureScript tests using Leiningen's 'doo' plugin. The 'node test-build once' part specifies running tests once using Node.js. ```Shell lein javac lein doo node test-build once ``` -------------------------------- ### Run All Project Benchmarks Source: https://github.com/redplanetlabs/specter/blob/master/DEVELOPER.md Execute all defined benchmarks within the project by running the provided shell script. This is useful for a comprehensive performance overview. ```Shell scripts/run-benchmarks ``` -------------------------------- ### New Navigators and Navigator Constructors (Specter 0.11.0) Source: https://github.com/redplanetlabs/specter/blob/master/CHANGES.md Introduces several new navigators: `must` for conditional key navigation, `continuous-subseqs` for sequence processing, and `ATOM`. Also adds `defnavconstructor` for defining flexible, high-performance parameterized navigator functions that integrate with inline caching. ```APIDOC New Navigators: - must: Navigates to a key if and only if it exists in the structure. - continuous-subseqs: For navigating continuous subsequences. - ATOM: A new navigator (contributed by @rakeshp). New Feature: - Navigator Constructors (via defnavconstructor): - Allows defining flexible functions to parameterize a defnav. - Integrates with inline caching for high performance. ``` -------------------------------- ### Path Parameterization and Map Entry Coercion (Specter 0.9.3) Source: https://github.com/redplanetlabs/specter/blob/master/CHANGES.md Enhances `declarepath` to be parameterizable, enabling more flexible path definitions. Introduces `params-reset` for recursive parameterized paths. `ALL` on maps now automatically coerces `MapEntry` to a vector for smoother transformations. `VOID` is renamed to `STOP`. ```APIDOC Improvements: - declarepath: Can now be parameterized. - ALL on maps: Auto-coerces MapEntry to vector for smoother transformations. - defprotocolpath: Added convenience syntax for no-params version (e.g., (defprotocolpath foo)). New Function: - params-reset: Calls its path with the params index walked back, enabling recursive parameterized paths. BREAKING CHANGE: - Rename: VOID -> STOP. ``` -------------------------------- ### Specter `defnav` Generated Helper Functions API Source: https://github.com/redplanetlabs/specter/blob/master/CHANGES.md The `defnav` macro now automatically generates helper functions for every method defined within it. These helpers provide direct access to the underlying select and transform logic, taking `key`, `structure`, and `next-fn` as parameters. ```APIDOC `keypath` now has helpers `keypath-select*` and `keypath-transform*`. These functions take parameters `[key structure next-fn]`. ``` -------------------------------- ### Select Funds from User and Family Accounts (Clojure) Source: https://github.com/redplanetlabs/specter/blob/master/README.md Demonstrates how to use `select` with `ALL` and `AccountPath` to extract specific values (funds) from a nested list of `User` and `Family` objects, showing the resulting flat list of funds. ```Clojure user> (select [ALL AccountPath :funds] [(->User (->Account 50)) (->User (->Account 51)) (->Family [(->Account 1) (->Account 2)]) ]) [50 51 1 2] ``` -------------------------------- ### New Selectors and Recursive Path Capabilities (Specter 0.9.2) Source: https://github.com/redplanetlabs/specter/blob/master/CHANGES.md Introduces `VOID` and `STAY` selectors, along with `stay-then-continue` and `continue-then-stay` for pre-order/post-order traversals. `declarepath` and `providepath` are added to enable arbitrary recursive or mutually recursive paths. `paramspath` is renamed to `path`. ```APIDOC New Selectors: - VOID: Navigates nowhere. - STAY: Stays at the current location. - stay-then-continue: Enables pre-order traversals. - continue-then-stay: Enables post-order traversals. New Features: - declarepath, providepath: Enable arbitrary recursive or mutually recursive paths. BREAKING CHANGE: - Rename: paramspath -> path. ``` -------------------------------- ### Core Functions Converted to Macros & Performance Boost (Specter 0.11.0) Source: https://github.com/redplanetlabs/specter/blob/master/CHANGES.md BREAKING CHANGE: `select`, `transform`, `setval`, and `replace-in` functions are now macros, moved to `com.rpl.specter.macros`. They automatically wrap paths with the new `path` macro, enabling inline caching and offering substantial performance improvements (up to 100x without explicit precompilation, and within 2-15% of explicitly precompiled usage). Corresponding `*` functions are added for old functionality. ```APIDOC BREAKING CHANGE: Functions: select, transform, setval, replace-in New Type: Macros New Namespace: com.rpl.specter.macros Behavior: Automatically wrap provided path in `path` macro for inline caching. Performance: Up to 100x improvement without explicit precompilation. Added: Functions: select*, transform*, setval*, replace-in* (retain old function behavior). ``` -------------------------------- ### Defining Parameterized Protocol Paths with `defprotocolpath` in Clojure Source: https://github.com/redplanetlabs/specter/blob/master/CHANGES.md This snippet demonstrates the new way to define parameterized protocol paths using `defprotocolpath` and `extend-protocolpath`. Parameters are now specified directly in the extension, replacing the old method where paths could be compiled without parameters. ```clojure (defprotocolpath MyProtPath [a]) (extend-protocolpath MyProtPath clojure.lang.PersistentArrayMap (must a)) ``` -------------------------------- ### ClojureScript Namespace Declarations for Specter Source: https://github.com/redplanetlabs/specter/blob/master/README.md Provides recommended namespace declaration patterns for using Specter in ClojureScript projects, specifically addressing the limitations of `use` and `refer :all` in ClojureScript by showing `as` and `refer-macros` options. ```Clojure (:require [com.rpl.specter :as s]) (:require [com.rpl.specter :as s :refer-macros [select transform]]) ;; add in the Specter macros that you need ``` -------------------------------- ### Specter Debugging with `with-inline-debug` Macro Source: https://github.com/redplanetlabs/specter/blob/master/CHANGES.md The `with-inline-debug` macro has been added to assist with debugging. When used, it prints information about the code being analyzed and produced by Specter's inline compiler and cacher, aiding in understanding and optimizing path compilation. ```APIDOC Macro: `with-inline-debug` Purpose: Prints information about code analyzed and produced by the inline compiler/cacher. ``` -------------------------------- ### New `path` Macro for Inline Caching (Specter 0.11.0) Source: https://github.com/redplanetlabs/specter/blob/master/CHANGES.md Introduces the `path` macro, which intelligently caches path components for significant performance improvements. It separates paths into static and dynamic parts, compiling the static part once for reuse. This can lead to up to 100x performance improvement for common operations. ```APIDOC Macro: path Description: Intelligent inline caching for paths. Behavior: - Factors path into a static portion and dynamic parameters. - Static part is compiled and cached on first use. - Dynamic parameters are provided on each execution. - No caching if precompilation is not possible (e.g., [ALL some-local-variable]). Example: [ALL (keypath k)] factors into [ALL keypath] (cached) and [k] (dynamic). ``` -------------------------------- ### Define and Extend Protocol Paths for Polymorphic Navigation (Clojure Specter) Source: https://github.com/redplanetlabs/specter/blob/master/README.md Explains how to define a `defprotocolpath` and `extend-protocolpath` to enable dynamic path selection based on the type of the navigated element, supporting polymorphic data structures. ```Clojure (defrecord Account [funds]) (defrecord User [account]) (defrecord Family [accounts-list]) (defprotocolpath AccountPath []) (extend-protocolpath AccountPath User :account Family [:accounts-list ALL]) ``` -------------------------------- ### Specter Performance Improvements for Dynamic Parameters and Maps Source: https://github.com/redplanetlabs/specter/blob/master/CHANGES.md Significant performance improvements have been made for paths utilizing dynamic parameters. Additionally, the performance of `ALL` and `MAP-VALS` operations on `PersistentArrayMap` has been approximately doubled. Inline factoring now immediately parameterizes navigators with constant parameters, resulting in leaner and faster code. ```APIDOC Improved performance of paths using dynamic parameters. Improved performance of `ALL` and `MAP-VALS` on `PersistentArrayMap` by ~2x. Inline factoring now parameterizes navigators immediately when all parameters are constants. ``` -------------------------------- ### Specter Navigator Definition with `defnav` and `IndirectNav` Source: https://github.com/redplanetlabs/specter/blob/master/CHANGES.md All navigators must now be defined using `defnav` and its variations from `com.rpl.specter`. Direct extension of core protocols is no longer supported. Existing types can be converted into navigators using the new `IndirectNav` protocol, providing a standardized way to integrate custom types. ```APIDOC Navigators must be defined with `defnav`. Core protocols may no longer be extended directly. Existing types can be turned into navigators with the `IndirectNav` protocol. ``` -------------------------------- ### New Paths and Core Improvements (Specter 0.10.0) Source: https://github.com/redplanetlabs/specter/blob/master/CHANGES.md Adds `parser`, `submap`, and `subselect` paths for more flexible data manipulation. `ALL` now maintains the type of queues, and the filterer is fixed to maintain the input sequence type in transforms. Zipper navigation is integrated into `com.rpl.specter.zipper`. ```APIDOC New Paths: - parser - submap - subselect Improvements: - ALL: Now maintains the type of queues. - Filterer: Fixed to maintain the type of the input sequence in transforms. - Zipper Navigation: Integrated into com.rpl.specter.zipper namespace. ``` -------------------------------- ### Specter `defdynamicnav` Replacement for `defpathedfn` Source: https://github.com/redplanetlabs/specter/blob/master/CHANGES.md The `defpathedfn` macro has been removed and replaced by the more generic `defdynamicnav`. `defdynamicnav` functions similarly to a macro, accepting parameters seen during inline caching. The `dynamic-param?` function helps distinguish between statically specified and dynamic parameters, often used with `late-bound-nav`. ```APIDOC Removed: `defpathedfn` Replaced by: `defdynamicnav` Behavior: Works similar to a macro, takes parameters seen during inline caching. Function: `dynamic-param?` to distinguish static vs. dynamic parameters. Typical Use: In conjunction with `late-bound-nav`. ``` -------------------------------- ### Navigate Maps with String Keys (Clojure Specter) Source: https://github.com/redplanetlabs/specter/blob/master/README.md Illustrates accessing values in maps using string keys as selectors. ```Clojure user> (select ["a" "b"] {"a" {"b" 10}}) [10] ``` -------------------------------- ### Specter Local Recursive Paths with `local-declarepath` and `providepath` Source: https://github.com/redplanetlabs/specter/blob/master/CHANGES.md The `local-declarepath` macro is introduced to facilitate the creation of local recursive or mutually recursive paths. It is designed to be used in conjunction with `providepath`, enabling complex local path definitions. ```APIDOC Macro: `local-declarepath` Purpose: Assists in making local recursive or mutually recursive paths. Usage: Use with `providepath`. ``` -------------------------------- ### Late-Bound Parameterization Enhancements (Specter 0.7.1) Source: https://github.com/redplanetlabs/specter/blob/master/CHANGES.md Expands late-bound parameterization capabilities to `view`, `walker`, and `codewalker`. Introduces `pred` as a late-bound parameterized version of using a function as a selector, and `paramsfn` as a helper macro for defining filter functions that accept late-bound parameters. ```APIDOC Enhanced Late-Bound Parameterization: - view: Can now be late-bound parameterized. - walker: Can now be late-bound parameterized. - codewalker: Can now be late-bound parameterized. New Selector: - pred: A late-bound parameterized version of using a function as a selector. New Macro: - paramsfn: Helper macro for defining filter functions that take late-bound parameters. ``` -------------------------------- ### Specter Namespace Consolidation: `com.rpl.specter.macros` Removal Source: https://github.com/redplanetlabs/specter/blob/master/CHANGES.md The `com.rpl.specter.macros` namespace has been removed. All macros previously residing in this namespace have been moved into the core `com.rpl.specter` namespace, simplifying the library's structure and import requirements. ```APIDOC Namespace: `com.rpl.specter.macros` removed. Macros: All moved into core `com.rpl.specter` namespace. ``` -------------------------------- ### Specter Inline Caching Improvements Source: https://github.com/redplanetlabs/specter/blob/master/CHANGES.md Inline caching now supports locals, dynamic vars, and special forms when used in the nav position. These values are coerced to navigators at runtime if they are vectors or implicit navigators (e.g., keywords). The `^:direct-nav` metadata hint can be used to bypass this coercion if values are known to implement `RichNavigator`. ```APIDOC Inline caching now works with locals, dynamic vars, and special forms in nav position. Runtime coercion: Values coerced to navigator if vector or implicit nav. Hint: `^:direct-nav` metadata to remove coercion if values are `RichNavigator`. ``` -------------------------------- ### clj-kondo Configuration for Specter Macros Source: https://github.com/redplanetlabs/specter/blob/master/README.md Provides a `clj-kondo` configuration snippet to resolve 'unresolved var' issues that arise when using Specter macros. This configuration maps Specter's internal macro definitions to `clojure.core/defn` or `clojure.core/def` to ensure proper linting. ```Clojure {:lint-as {com.rpl.specter/defcollector clojure.core/defn com.rpl.specter/defdynamicnav clojure.core/defn com.rpl.specter/defmacroalias clojure.core/def com.rpl.specter/defnav clojure.core/defn com.rpl.specter/defrichnav clojure.core/defn}} ``` -------------------------------- ### Specter Path Compilation and Parameterization Changes Source: https://github.com/redplanetlabs/specter/blob/master/CHANGES.md Paths can no longer be compiled without their parameters. Instead, the `path` macro must be used to handle parameterization. This change ensures that paths are always fully specified when compiled, aligning with the new parameterized protocol path behavior. ```APIDOC Paths can no longer be compiled without their parameters. Use the `path` macro to handle parameterization. ``` -------------------------------- ### New Collection Selectors (Specter 0.8.0) Source: https://github.com/redplanetlabs/specter/blob/master/CHANGES.md Adds `subset` selector for sets, similar to `srange`. Introduces `nil->val`, `NIL->SET`, `NIL->LIST`, and `NIL->VECTOR` selectors to simplify manipulation of maps, allowing values to be initialized from `nil` to a specified collection type. ```APIDOC New Selectors: - subset: Like srange, but for sets. - nil->val: Converts nil to a specified value. - NIL->SET: Converts nil to an empty set. - NIL->LIST: Converts nil to an empty list. - NIL->VECTOR: Converts nil to an empty vector. Usage Example: (setval [:akey NIL->VECTOR END] [:a :b] amap) to append to a map value, even if it's nil. ``` -------------------------------- ### Specter `IndirectNav` Protocol for Value Type Conversion Source: https://github.com/redplanetlabs/specter/blob/master/CHANGES.md The `IndirectNav` protocol has been added to allow any value type to be transformed into a navigator. This provides a flexible mechanism for integrating custom data structures or values directly into Specter's navigation system. ```APIDOC Protocol: `IndirectNav` Purpose: For turning a value type into a navigator. ``` -------------------------------- ### Specter Protocol Change: `Navigator` to `RichNavigator` Source: https://github.com/redplanetlabs/specter/blob/master/CHANGES.md The core protocol `Navigator` has been renamed to `RichNavigator`. All functions within this protocol now require an additional argument, necessitating updates to existing navigator implementations. This change impacts how navigators are defined and interact with the Specter library. ```APIDOC Protocol: `Navigator` changed to `RichNavigator` Functions: Now have an extra argument. ``` -------------------------------- ### Specter `late-bound-nav` Replacement for Pathed Navigators Source: https://github.com/redplanetlabs/specter/blob/master/CHANGES.md The `fixed-pathed-nav` and `variable-pathed-nav` have been removed and replaced by the more generic `late-bound-nav`. This new navigator allows normal values to be late-bound parameterized, not just paths. The `late-path` function is used to indicate which parameters are paths, and static bindings lead to immediate resolution and caching. ```APIDOC Removed: `fixed-pathed-nav`, `variable-pathed-nav` Replaced by: `late-bound-nav` Usage: `late-bound-nav` can have normal values be late-bound parameterized. Function: `late-path` to indicate path parameters. Behavior: If all bindings are static, navigator resolves and caches immediately. ``` -------------------------------- ### Path/Collector Renames and Protocol Paths (Specter 0.9.0) Source: https://github.com/redplanetlabs/specter/blob/master/CHANGES.md BREAKING CHANGE: `defparamspath` and `defparamscollector` are renamed to `defpath` and `defcollector` respectively. Protocol paths are implemented for the Clojure version, allowing for more flexible path definitions. ```APIDOC BREAKING CHANGES: - Rename: defparamspath -> defpath - Rename: defparamscollector -> defcollector New Feature (Clojure only): - Protocol Paths: Implemented for Clojure version (see #38). ``` -------------------------------- ### Conditional Transformation with `if-path` (Clojure Specter) Source: https://github.com/redplanetlabs/specter/blob/master/README.md Illustrates using `if-path` to apply different transformations based on a condition evaluated at a specific path within the data structure. ```Clojure user> (transform [ALL (if-path [:a even?] [:c ALL] :d)] inc [{:a 2 :c [1 2] :d 4} {:a 4 :c [0 10 -1]} {:a -1 :c [1 1 1] :d 1}]) [{:c [2 3], :d 4, :a 2} {:c [1 11 0], :a 4} {:c [1 1 1], :d 2, :a -1}] ``` -------------------------------- ### Remove Key-Value Pair and Compact Empty Maps (Clojure Specter) Source: https://github.com/redplanetlabs/specter/blob/master/README.md Demonstrates how to remove a key-value pair and automatically remove any parent maps that become empty as a result, using `compact`. ```Clojure user> (setval [:a (compact :b :c)] NONE {:a {:b {:c 1}}}) {} ``` -------------------------------- ### Increment Even Values for Specific Keys in Map Sequence (Clojure Specter) Source: https://github.com/redplanetlabs/specter/blob/master/README.md Shows how to apply a transformation to even values associated with the `:a` key within a sequence of maps using `ALL` and a predicate. ```Clojure user> (transform [ALL :a even?] inc [{:a 1} {:a 2} {:a 4} {:a 3}]) [{:a 1} {:a 3} {:a 5} {:a 3}] ``` -------------------------------- ### Specter `must-cache-paths!` Removal Source: https://github.com/redplanetlabs/specter/blob/master/CHANGES.md The `must-cache-paths!` function has been removed. It is no longer relevant as all paths can now be compiled and cached automatically, eliminating the need for explicit caching directives. ```APIDOC Removed: `must-cache-paths!` Reason: All paths can now be compiled and cached automatically. ``` -------------------------------- ### Specter Codebase Migration to CLJC Source: https://github.com/redplanetlabs/specter/blob/master/CHANGES.md The Specter codebase has been switched from `cljx` to `cljc`. This migration allows the library to be compiled for both Clojure and ClojureScript environments from a single source, enhancing cross-platform compatibility. ```APIDOC Codebase switched from `cljx` to `cljc`. ``` -------------------------------- ### Specter Internal Redesign for Navigator Dispatch Source: https://github.com/redplanetlabs/specter/blob/master/CHANGES.md Specter's internals have been redesigned to utilize interface dispatch for navigators. This change means that transform and selection functions are no longer stored as separate fields, leading to a more streamlined and potentially more performant internal architecture. ```APIDOC Navigators now use interface dispatch. Transform/selection functions no longer stored as separate fields. ``` -------------------------------- ### Select All Numbers from Nested Data Structure (Clojure Specter) Source: https://github.com/redplanetlabs/specter/blob/master/README.md Shows how to extract all numeric values from a deeply nested and mixed data structure using the `walker` function. ```Clojure user> (select (walker number?) {2 [1 2 [6 7]] :a 4 :c {:a 1 :d [2 nil]}}) [2 1 2 1 2 6 7 4] ``` -------------------------------- ### Select Numbers Divisible by 3 from Nested Sequences (Clojure Specter) Source: https://github.com/redplanetlabs/specter/blob/master/README.md Illustrates selecting specific elements from deeply nested sequences using `ALL` and a custom predicate function. ```Clojure user> (select [ALL ALL #(= 0 (mod % 3))] [[1 2 3 4] [] [5 3 2 18] [2 4 6] [12]]) [3 3 18 6 12] ``` -------------------------------- ### Double Even Numbers in a Tree using Protocol Paths (Clojure) Source: https://github.com/redplanetlabs/specter/blob/master/README.md Illustrates recursive navigation using `defprotocolpath` and `extend-protocolpath` to define a custom walker. It then uses `transform` to double all even numbers found within a nested vector (tree structure). ```Clojure (defprotocolpath TreeWalker []) (extend-protocolpath TreeWalker Object nil clojure.lang.PersistentVector [ALL TreeWalker]) (transform [TreeWalker number? even?] #(* 2 %) [:a 1 [2 [[[3]]] :e] [4 5 [6 7]]]) ;; => [:a 1 [4 [[[3]]] :e] [8 5 [12 7]]] ``` -------------------------------- ### Path/Nav Renames and Path Caching Enforcement (Specter 0.11.0) Source: https://github.com/redplanetlabs/specter/blob/master/CHANGES.md BREAKING CHANGE: `defpath` is renamed to `defnav`, and `path` is renamed to `nav`. Related `fixed-pathed-path` and `variable-pathed-path` are also renamed to `fixed-pathed-nav` and `variabled-pathed-nav`. A new `must-cache-paths!` function is introduced to enforce path factorability for caching, throwing an error if not possible. ```APIDOC BREAKING CHANGES: Rename: defpath -> defnav Rename: path -> nav Rename: fixed-pathed-path -> fixed-pathed-nav Rename: variable-pathed-path -> variabled-pathed-nav New Function: Function: must-cache-paths! Description: Throws an error if a path cannot be factored into a static portion and dynamic parameters for caching. ``` -------------------------------- ### Collect External Values with `putval` (Clojure Specter) Source: https://github.com/redplanetlabs/specter/blob/master/README.md Demonstrates `putval`, which adds an arbitrary external value into the collected values list passed to the transform function. ```Clojure user> (transform [:a (putval 10)] + {:a 1 :b 3}) {:b 3 :a 11} ``` -------------------------------- ### Reverse Even Numbers in Sequence Range (Clojure Specter) Source: https://github.com/redplanetlabs/specter/blob/master/README.md Demonstrates reversing the order of even numbers within a specified index range using `srange` and `filterer`. ```Clojure user> (transform [(srange 4 11) (filterer even?)] reverse [0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15]) [0 1 2 3 10 5 8 7 6 9 4 11 12 13 14 15] ``` -------------------------------- ### Replace Subsequence in Vector (Clojure Specter) Source: https://github.com/redplanetlabs/specter/blob/master/README.md Illustrates replacing a portion of a sequence defined by a range with a new sequence using `setval` and `srange`. ```Clojure user> (setval (srange 2 4) [:a :b :c :d :e] [0 1 2 3 4 5 6 7 8 9]) [0 1 :a :b :c :d :e 4 5 6 7 8 9] ``` -------------------------------- ### Concatenate Sequence to Nested Sequences (Clojure Specter) Source: https://github.com/redplanetlabs/specter/blob/master/README.md Demonstrates appending a sequence to the end of every nested sequence within a data structure using `setval` and `END`. ```Clojure user> (setval [ALL END] [:a :b] [[1] '(1 2) [:c]]) [[1 :a :b] (1 2 :a :b) [:c :a :b]] ``` -------------------------------- ### Increment Values in Nested Maps (Clojure Specter) Source: https://github.com/redplanetlabs/specter/blob/master/README.md Demonstrates how to use `MAP-VALS` to recursively increment all numeric values within nested maps. ```Clojure 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}} ``` -------------------------------- ### Specter Bug Fix: PersistentArrayMap Transforms Output Source: https://github.com/redplanetlabs/specter/blob/master/CHANGES.md A bug has been fixed where `ALL` and `MAP-VALS` transforms on `PersistentArrayMap` above a certain threshold incorrectly output `PersistentHashMap`. The fix ensures that these transforms now correctly output `PersistentArrayMap`, maintaining data structure consistency. ```APIDOC Bug fix: `ALL` and `MAP-VALS` transforms on `PersistentArrayMap` above threshold now output `PersistentArrayMap` instead of `PersistentHashMap`. ``` -------------------------------- ### Increment Last Odd Number in Sequence (Clojure Specter) Source: https://github.com/redplanetlabs/specter/blob/master/README.md Demonstrates using `filterer` to target odd numbers and `LAST` to select the final matching element for transformation. ```Clojure user> (transform [(filterer odd?) LAST] inc [2 1 3 6 9 4 8]) [2 1 3 6 10 4 8] ``` -------------------------------- ### Append to Subsequences with Minimum Even Numbers (Clojure Specter) Source: https://github.com/redplanetlabs/specter/blob/master/README.md Shows conditional appending to subsequences based on a predicate that checks if the subsequence contains at least two even numbers, using `selected?`, `view count`, and `pred>=`. ```Clojure user> (setval [ALL (selected? (filterer even?) (view count) (pred>= 2)) END] [:c :d] [[1 2 3 4 5 6] [7 0 -1] [8 8] []]) [[1 2 3 4 5 6 :c :d] [7 0 -1] [8 8 :c :d] []] ``` -------------------------------- ### Remove Nil Values from Nested Sequence (Clojure Specter) Source: https://github.com/redplanetlabs/specter/blob/master/README.md Shows how to remove `nil` values from a sequence nested within a map using `setval` and `NONE`. ```Clojure user> (setval [:a ALL nil?] NONE {:a [1 2 nil 3 nil]}) {:a [1 2 3]} ``` -------------------------------- ### Remove Key-Value Pair from Nested Map (Clojure Specter) Source: https://github.com/redplanetlabs/specter/blob/master/README.md Illustrates removing a specific key-value pair from a deeply nested map using `setval` and `NONE`. ```Clojure user> (setval [:a :b :c] NONE {:a {:b {:c 1}}}) {:a {:b {}}} ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.