From afbb8d284349c46f8c5cd999e21f95c62572fda9 Mon Sep 17 00:00:00 2001 From: Asko Nõmm Date: Wed, 24 Sep 2025 10:09:05 +0300 Subject: Improve performance of the $ macro. --- src/dompa/nodes.cljc | 1 - src/dompa/utils.cljc | 56 +++++++++++++++++++++++++++++++--------------------- 2 files changed, 34 insertions(+), 23 deletions(-) (limited to 'src/dompa') diff --git a/src/dompa/nodes.cljc b/src/dompa/nodes.cljc index dfd93bc..295e755 100644 --- a/src/dompa/nodes.cljc +++ b/src/dompa/nodes.cljc @@ -62,7 +62,6 @@ - `:wbr` " ([nodes] - (prn "nodes: " nodes) (->html nodes {:void-nodes default-void-nodes})) ([nodes {:keys [void-nodes]}] (-> (node->html-reducer-fn void-nodes ->html) diff --git a/src/dompa/utils.cljc b/src/dompa/utils.cljc index 74185b5..0e17875 100644 --- a/src/dompa/utils.cljc +++ b/src/dompa/utils.cljc @@ -1,5 +1,6 @@ (ns dompa.utils - (:require [dompa.nodes :as nodes])) + (:require [dompa.nodes :as nodes] + [criterium.core :as c])) (defmacro defhtml {:clj-kondo/lint-as 'clojure.core/defn} @@ -8,35 +9,46 @@ `(defn ~name ~args (nodes/->html (vector ~@elements))))) -(defn- flattench [children] - (mapcat #(if (sequential? %) (flattench %) [%]) children)) +(defn flattench-xf [] + (fn [rf] + (letfn [(step [result input] + (if (sequential? input) + (reduce step result input) ;; recursively reduce over nested seq + (rf result input)))] ;; apply rf with accumulator + value + (fn + ([] (rf)) ;; init + ([result] (rf result)) ;; completion + ([result input] (step result input)))))) ;; step + +(defn flattench [children] + (into [] (flattench-xf) children)) (defmacro $ {:clj-kondo/lint-as 'clojure.core/list} [name & opts] `(if (string? ~name) {:node/name :dompa/text - :node/value (apply str ~name ~opts)} - (let [name# ~name - opts-list# (list ~@opts) - first-opt# (first opts-list#) + :node/value (apply str ~name ~@opts)} + (let [opts# (list ~@opts) + first-opt# (first opts#) attrs?# (and (map? first-opt#) (not (contains? first-opt# :node/name))) attrs# (if attrs?# first-opt# {}) - children# (if attrs?# (rest opts-list#) opts-list#)] - (merge - {:node/name name#} - (when attrs?# {:node/attrs attrs#}) - (when (seq children#) {:node/children (flattench children#)}))))) + children# (if attrs?# (rest opts#) opts#)] + (cond-> {:node/name ~name} + attrs?# (assoc :node/attrs attrs#) + (seq children#) (assoc :node/children (flattench children#)))))) + +(defn bench-n [] + (c/quick-bench + (dotimes [_ 1500] + ($ :div {:class "container"} + (map #($ %) ["a" "b" "c"]) + ($ "hello world"))))) -(defhtml page [who] - ($ :div {:class "test"} - ($ "hello world") - (let [n "who"] - ($ n)) - (for [x ["1" "2" "3"]] - ($ x)) - ($ who) - (mapv #($ %) ["a" "b" "c"]))) +(defhtml test-page [] + ($ :div + (map #($ %) ["a" "b" "c"]) + ($ "hello world"))) -(page "world") \ No newline at end of file +(test-page) -- cgit v1.2.3