Closed nathanmarz closed 6 years ago
Here's an even simpler approach:
(defdynamicnav ensure-matching* [path]
(multi-path path (if-path path STOP (terminal-val NONE))))
(def ensure-matching (eachnav ensure-matching*))
(transform
[ALL
(ensure-matching (must :a) ALL (must :b))
]
str
data)
One common use case that should be addressed here is removal of a subvalue if it is an empty collection.
Here's a potential solution for removing when empty:
(let [ensure* (stay-then-continue (if-path empty? (terminal-val NONE)))]
(defdynamicnav ensure [& path]
(interleave (repeat (count path) ensure*) path)
))
(setval [:a (ensure :b :c)] NONE {:a {:b {:c 1}}})
;; => {}
(setval [:a (ensure :b :c)] NONE {:a {:b {:c 1} :d 2}})
;; => {:a {:d 2}}
Need a different name than ensure
since Clojure already has a function named ensure
.
Name ideas: compact
, trim
, tighten
To make these navigators work for both select
and transform
, need to turn terminal
and vterminal
into no-ops for select*
instead of throwing exceptions as they do now.
compact
is implemented in master. Other kinds of related navigators are too application-specific to add to Specter, whereas removing empty subvalues is a common, generic use case.
These could be called "ensure" operations, e.g.: