This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2023-05-06
Channels
- # babashka (130)
- # beginners (97)
- # biff (36)
- # calva (6)
- # cherry (23)
- # clojure (29)
- # clojure-dev (1)
- # clojure-europe (9)
- # clojurescript (5)
- # datomic (24)
- # emacs (13)
- # fulcro (5)
- # hyperfiddle (33)
- # interop (2)
- # jobs (18)
- # kaocha (1)
- # london-clojurians (1)
- # lsp (20)
- # nrepl (1)
- # off-topic (60)
- # pathom (4)
- # reitit (7)
- # releases (1)
- # remote-jobs (4)
- # scittle (3)
- # specter (1)
- # tools-deps (7)
- # xtdb (16)
Given some hiccup like structure I want to find all things with a tag and a "particular" path to get to the thing. I have a solution but I am not too keen its use of collected.
(require '[com.rpl.specter :as S])
(require '[com.rpl.specter.impl :as i])
(require '[com.rpl.specter.util-macros :as sum])
(defn tag?
[tag-name]
#(and (vector? %) (= tag-name (first %))))
;; Based on INDEXED-VALS
(S/defnav
INDEXED-HEADLINES
[]
(select* [this structure next-fn]
;; could be more efficient with a primitive mutable field
(let [ih (i/mutable-cell -1)
io (i/mutable-cell -1)]
(sum/doseqres S/NONE [e structure]
(let [cell (if ((tag? :headline) e) ih io)]
(i/update-cell! cell inc)
(next-fn [(i/get-cell cell) e])))))
;; TODO: update this like the select*. Outside of scope
(transform* [this structure next-fn]
(throw (ex-info "not implemented" {}))))
;; Based on code from
(def headline-path-walker
(S/recursive-path [] p
(S/if-path sequential?
[INDEXED-HEADLINES
(S/if-path [S/LAST (tag? :headline)]
(S/multi-path
[(S/collect-one S/FIRST)
S/LAST]
[(S/collect-one S/FIRST)
S/LAST
p])
[(S/collect-one S/FIRST) S/LAST p])])))
So evaluating
(let [s [:doc
[:ignore-this]
[:headline
[:title [:text [:text-normal "headline"]]]
[:section]
[:headline
[:title [:text [:text-normal "child"]]]
[:section]
[:headline
[:title [:text [:text-normal "grandchild"]]]
[:section]]
[:headline
[:title [:text [:text-normal "grandchild2"]]]
[:section]]]]
[:headline
[:title [:text [:text-normal "other headline"]]]
[:section]]]]
(S/select [headline-path-walker
(S/nthpath 1)]
s))
Results in
[[0 [:title [:text [:text-normal "headline"]]]]
[0 0 [:title [:text [:text-normal "child"]]]]
[0 0 0 [:title [:text [:text-normal "grandchild"]]]]
[0 0 1 [:title [:text [:text-normal "grandchild2"]]]]
[1 [:title [:text [:text-normal "other headline"]]]]]
One issue I have is that headline-path-walker
results in stuff getting added to collected. I would prefer if it used collect internally but returned a collection of [[0 1 2 ...] [:headline ...]]
. Is there any way to do this? I have played around with S/transformed
but to no avail.