🎉 Add specific namespace for data macros

And additionally add optimized macros for get-in,
select-keys and str.
This commit is contained in:
Andrey Antukh 2022-02-24 23:36:53 +01:00 committed by Alonso Torres
parent 165c551e39
commit 84a36624a6
9 changed files with 277 additions and 184 deletions

View file

@ -417,45 +417,6 @@
(not (mth/finite? v))
(mth/nan? v)) default v)))
(defmacro export
"A helper macro that allows reexport a var in a current namespace."
[v]
(if (boolean (:ns &env))
;; Code for ClojureScript
(let [mdata (aapi/resolve &env v)
arglists (second (get-in mdata [:meta :arglists]))
sym (symbol (core/name v))
andsym (symbol "&")
procarg #(if (= % andsym) % (gensym "param"))]
(if (pos? (count arglists))
`(def
~(with-meta sym (:meta mdata))
(fn ~@(for [args arglists]
(let [args (map procarg args)]
(if (some #(= andsym %) args)
(let [[sargs dargs] (split-with #(not= andsym %) args)]
`([~@sargs ~@dargs] (apply ~v ~@sargs ~@(rest dargs))))
`([~@args] (~v ~@args)))))))
`(def ~(with-meta sym (:meta mdata)) ~v)))
;; Code for Clojure
(let [vr (resolve v)
m (meta vr)
n (:name m)
n (with-meta n
(cond-> {}
(:dynamic m) (assoc :dynamic true)
(:protocol m) (assoc :protocol (:protocol m))))]
`(let [m# (meta ~vr)]
(def ~n (deref ~vr))
(alter-meta! (var ~n) merge (dissoc m# :name))
;; (when (:macro m#)
;; (.setMacro (var ~n)))
~vr))))
(defn any-key? [element & rest]
(some #(contains? element %) rest))
@ -692,4 +653,3 @@
(recur acc (step k))
acc)))
acc))))))

View file

@ -0,0 +1,130 @@
;; This Source Code Form is subject to the terms of the Mozilla Public
;; License, v. 2.0. If a copy of the MPL was not distributed with this
;; file, You can obtain one at http://mozilla.org/MPL/2.0/.
;;
;; Copyright (c) UXBOX Labs SL
(ns app.common.data.macros
"Data retrieval & manipulation specific macros."
(:refer-clojure :exclude [get-in select-keys str])
#?(:cljs (:require-macros [app.common.data.macros]))
(:require
#?(:clj [clojure.core :as c]
:cljs [cljs.core :as c])
[cljs.analyzer.api :as aapi]))
(defmacro select-keys
"A macro version of `select-keys`. Usefull when keys vector is known
at compile time (aprox 600% performance boost).
It is not 100% equivalent, this macro does not removes not existing
keys in contrast to clojure.core/select-keys"
[target keys]
(assert (vector? keys) "keys expected to be a vector")
`{ ~@(mapcat (fn [key] [key (list `c/get target key)]) keys) ~@[] })
(defmacro get-in
"A macro version of `get-in`. Usefull when the keys vector is known at
compile time (20-40% performance improvement)."
([target keys]
(assert (vector? keys) "keys expected to be a vector")
`(-> ~target ~@(map (fn [key] (list `c/get key)) keys)))
([target keys default]
(assert (vector? keys) "keys expected to be a vector")
`(let [v# (-> ~target ~@(map (fn [key] (list `c/get key)) keys))]
(if (some? v#) v# ~default))))
;; => benchmarking: clojure.core/str
;; --> WARM: 100000
;; --> BENCH: 500000
;; --> TOTAL: 197.82ms
;; --> MEAN: 395.64ns
;; => benchmarking: app.commons.data.macros/str
;; --> WARM: 100000
;; --> BENCH: 500000
;; --> TOTAL: 20.31ms
;; --> MEAN: 40.63ns
(defmacro str
"CLJS only macro variant of `str` function that performs string concat much faster."
([a]
(if (:ns &env)
(list 'js* "\"\"+~{}" a)
(list `c/str a)))
([a b]
(if (:ns &env)
(list 'js* "\"\"+~{}+~{}" a b)
(list `c/str a b)))
([a b c]
(if (:ns &env)
(list 'js* "\"\"+~{}+~{}+~{}" a b c)
(list `c/str a b c)))
([a b c d]
(if (:ns &env)
(list 'js* "\"\"+~{}+~{}+~{}+~{}" a b c d)
(list `c/str a b c d)))
([a b c d e]
(if (:ns &env)
(list 'js* "\"\"+~{}+~{}+~{}+~{}+~{}" a b c d e)
(list `c/str a b c d e)))
([a b c d e f]
(if (:ns &env)
(list 'js* "\"\"+~{}+~{}+~{}+~{}+~{}+~{}" a b c d e f)
(list `c/str a b c d e f)))
([a b c d e f g]
(if (:ns &env)
(list 'js* "\"\"+~{}+~{}+~{}+~{}+~{}+~{}+~{}" a b c d e f g)
(list `c/str a b c d e f g)))
([a b c d e f g h]
(if (:ns &env)
(list 'js* "\"\"+~{}+~{}+~{}+~{}+~{}+~{}+~{}+~{}" a b c d e f g h)
(list `c/str a b c d e f g h)))
([a b c d e f g h & rest]
(let [all (into [a b c d e f g h] rest)]
(if (:ns &env)
(let [xf (map (fn [items] `(str ~@items)))
pall (partition-all 8 all)]
(if (<= (count all) 64)
`(str ~@(sequence xf pall))
`(c/str ~@(sequence xf pall))))
`(c/str ~@all)))))
(defmacro export
"A helper macro that allows reexport a var in a current namespace."
[v]
(if (boolean (:ns &env))
;; Code for ClojureScript
(let [mdata (aapi/resolve &env v)
arglists (second (get-in mdata [:meta :arglists]))
sym (symbol (c/name v))
andsym (symbol "&")
procarg #(if (= % andsym) % (gensym "param"))]
(if (pos? (count arglists))
`(def
~(with-meta sym (:meta mdata))
(fn ~@(for [args arglists]
(let [args (map procarg args)]
(if (some #(= andsym %) args)
(let [[sargs dargs] (split-with #(not= andsym %) args)]
`([~@sargs ~@dargs] (apply ~v ~@sargs ~@(rest dargs))))
`([~@args] (~v ~@args)))))))
`(def ~(with-meta sym (:meta mdata)) ~v)))
;; Code for Clojure
(let [vr (resolve v)
m (meta vr)
n (:name m)
n (with-meta n
(cond-> {}
(:dynamic m) (assoc :dynamic true)
(:protocol m) (assoc :protocol (:protocol m))))]
`(let [m# (meta ~vr)]
(def ~n (deref ~vr))
(alter-meta! (var ~n) merge (dissoc m# :name))
;; (when (:macro m#)
;; (.setMacro (var ~n)))
~vr))))

View file

@ -7,6 +7,7 @@
(ns app.common.geom.shapes
(:require
[app.common.data :as d]
[app.common.data.macros :as dm]
[app.common.geom.point :as gpt]
[app.common.geom.shapes.bool :as gsb]
[app.common.geom.shapes.common :as gco]
@ -137,55 +138,55 @@
;; EXPORTS
(d/export gco/center-shape)
(d/export gco/center-selrect)
(d/export gco/center-rect)
(d/export gco/center-points)
(d/export gco/make-centered-rect)
(d/export gco/transform-points)
(dm/export gco/center-shape)
(dm/export gco/center-selrect)
(dm/export gco/center-rect)
(dm/export gco/center-points)
(dm/export gco/make-centered-rect)
(dm/export gco/transform-points)
(d/export gpr/rect->selrect)
(d/export gpr/rect->points)
(d/export gpr/points->selrect)
(d/export gpr/points->rect)
(d/export gpr/center->rect)
(d/export gpr/join-rects)
(d/export gpr/contains-selrect?)
(dm/export gpr/rect->selrect)
(dm/export gpr/rect->points)
(dm/export gpr/points->selrect)
(dm/export gpr/points->rect)
(dm/export gpr/center->rect)
(dm/export gpr/join-rects)
(dm/export gpr/contains-selrect?)
(d/export gtr/move)
(d/export gtr/absolute-move)
(d/export gtr/transform-matrix)
(d/export gtr/inverse-transform-matrix)
(d/export gtr/transform-point-center)
(d/export gtr/transform-rect)
(d/export gtr/calculate-adjust-matrix)
(d/export gtr/update-group-selrect)
(d/export gtr/resize-modifiers)
(d/export gtr/rotation-modifiers)
(d/export gtr/merge-modifiers)
(d/export gtr/transform-shape)
(d/export gtr/transform-selrect)
(d/export gtr/modifiers->transform)
(d/export gtr/empty-modifiers?)
(dm/export gtr/move)
(dm/export gtr/absolute-move)
(dm/export gtr/transform-matrix)
(dm/export gtr/inverse-transform-matrix)
(dm/export gtr/transform-point-center)
(dm/export gtr/transform-rect)
(dm/export gtr/calculate-adjust-matrix)
(dm/export gtr/update-group-selrect)
(dm/export gtr/resize-modifiers)
(dm/export gtr/rotation-modifiers)
(dm/export gtr/merge-modifiers)
(dm/export gtr/transform-shape)
(dm/export gtr/transform-selrect)
(dm/export gtr/modifiers->transform)
(dm/export gtr/empty-modifiers?)
;; Constratins
(d/export gct/calc-child-modifiers)
(dm/export gct/calc-child-modifiers)
;; PATHS
(d/export gsp/content->selrect)
(d/export gsp/transform-content)
(d/export gsp/open-path?)
(dm/export gsp/content->selrect)
(dm/export gsp/transform-content)
(dm/export gsp/open-path?)
;; Intersection
(d/export gin/overlaps?)
(d/export gin/has-point?)
(d/export gin/has-point-rect?)
(d/export gin/rect-contains-shape?)
(dm/export gin/overlaps?)
(dm/export gin/has-point?)
(dm/export gin/has-point-rect?)
(dm/export gin/rect-contains-shape?)
;; Bool
(d/export gsb/update-bool-selrect)
(d/export gsb/calc-bool-content)
(dm/export gsb/update-bool-selrect)
(dm/export gsb/calc-bool-content)
;; Constraints
(d/export gct/default-constraints-h)
(d/export gct/default-constraints-v)
(dm/export gct/default-constraints-h)
(dm/export gct/default-constraints-v)

View file

@ -7,32 +7,32 @@
(ns app.common.pages
"A common (clj/cljs) functions and specs for pages."
(:require
[app.common.data :as d]
[app.common.data.macros :as dm]
[app.common.pages.changes :as changes]
[app.common.pages.common :as common]
[app.common.pages.indices :as indices]
[app.common.pages.init :as init]))
;; Common
(d/export common/root)
(d/export common/file-version)
(d/export common/default-color)
(d/export common/component-sync-attrs)
(dm/export common/root)
(dm/export common/file-version)
(dm/export common/default-color)
(dm/export common/component-sync-attrs)
;; Indices
(d/export indices/calculate-z-index)
(d/export indices/update-z-index)
(d/export indices/generate-child-all-parents-index)
(d/export indices/generate-child-parent-index)
(d/export indices/create-clip-index)
(dm/export indices/calculate-z-index)
(dm/export indices/update-z-index)
(dm/export indices/generate-child-all-parents-index)
(dm/export indices/generate-child-parent-index)
(dm/export indices/create-clip-index)
;; Process changes
(d/export changes/process-changes)
(dm/export changes/process-changes)
;; Initialization
(d/export init/default-frame-attrs)
(d/export init/default-shape-attrs)
(d/export init/make-file-data)
(d/export init/make-minimal-shape)
(d/export init/make-minimal-group)
(d/export init/empty-file-data)
(dm/export init/default-frame-attrs)
(dm/export init/default-shape-attrs)
(dm/export init/make-file-data)
(dm/export init/make-minimal-shape)
(dm/export init/make-minimal-group)
(dm/export init/empty-file-data)

View file

@ -7,15 +7,15 @@
(ns app.common.uri
(:refer-clojure :exclude [uri?])
(:require
[app.common.data :as d]
[app.common.data.macros :as dm]
[lambdaisland.uri :as u]
[lambdaisland.uri.normalize :as un]))
(d/export u/uri)
(d/export u/join)
(d/export u/query-encode)
(d/export un/percent-encode)
(d/export u/uri?)
(dm/export u/uri)
(dm/export u/join)
(dm/export u/query-encode)
(dm/export un/percent-encode)
(dm/export u/uri?)
(defn query-string->map
[s]

View file

@ -7,7 +7,7 @@
(ns app.common.uuid
(:refer-clojure :exclude [next uuid zero?])
(:require
#?(:clj [app.common.data :as d])
#?(:clj [app.common.data.macros :as dm])
#?(:clj [clj-uuid :as impl])
#?(:clj [clojure.core :as c])
#?(:cljs [app.common.uuid-impl :as impl])
@ -47,4 +47,4 @@
([b a] #?(:clj (UUID. b a) :cljs (c/uuid (impl/custom b a)))))
#?(:clj
(d/export impl/get-word-high))
(dm/export impl/get-word-high))