|
254 | 254 | (def
|
255 | 255 | ^{:doc "Associate keys to values in associative data structure m. If m is nil,
|
256 | 256 | returns a new map with key-values kvs."
|
257 |
| - :arglists '([m & kvs])} |
| 257 | + :arglists '([m k v] [m k v & kvs])} |
258 | 258 | assoc
|
259 |
| - (fn assoc [m & kvs] |
260 |
| - (apply basilisp.lang.runtime/assoc m kvs))) |
| 259 | + (fn assoc |
| 260 | + ([m k v] |
| 261 | + (basilisp.lang.runtime/assoc m k v)) |
| 262 | + ([m k v & kvs] |
| 263 | + (apply basilisp.lang.runtime/assoc m k v kvs)))) |
261 | 264 |
|
262 | 265 | (def
|
263 | 266 | ^{:doc "Conjoin xs to collection. New elements may be added in different positions
|
264 | 267 | depending on the type of coll. conj returns the same type as coll. If coll
|
265 | 268 | is nil, return a list with xs conjoined."
|
266 |
| - :arglists '([coll & xs])} |
| 269 | + :arglists '([coll x] [coll x & xs])} |
267 | 270 | conj
|
268 |
| - (fn conj [coll & xs] |
269 |
| - (apply basilisp.lang.runtime/conj coll xs))) |
| 271 | + (fn conj |
| 272 | + ([coll x] |
| 273 | + (basilisp.lang.runtime/conj coll x)) |
| 274 | + ([coll x & xs] |
| 275 | + (apply basilisp.lang.runtime/conj coll x xs)))) |
270 | 276 |
|
271 | 277 | (def
|
272 | 278 | ^{:macro true
|
|
2014 | 2020 | [m]
|
2015 | 2021 | (seq (.values m)))
|
2016 | 2022 |
|
| 2023 | +;;;;;;;;;;;;;;;;;;;;;;;;;;; |
| 2024 | +;; Transient Collections ;; |
| 2025 | +;;;;;;;;;;;;;;;;;;;;;;;;;;; |
| 2026 | + |
| 2027 | +(defn transient |
| 2028 | + "Return a transient copy of persistent collection `coll`. |
| 2029 | + |
| 2030 | + Transients can be created from maps, sets, and vectors. Transients allow faster |
| 2031 | + mutations than their persistent counterparts and are useful for performance |
| 2032 | + sensitive code which makes many modifications to these data structures. |
| 2033 | + |
| 2034 | + Transient collections can be edited with the transient versions of the familiar |
| 2035 | + collection functions (depending on the type of `coll`): `assoc!`, `conj!`, |
| 2036 | + `disj!`, `dissoc!`, and `pop!`. Transient collections are designed to be used |
| 2037 | + in the same style as the builtin persistent collections, so callers should be |
| 2038 | + sure to use the returned value from prior calls to these collection functions |
| 2039 | + rather than repeatedly modifying the collection in place. |
| 2040 | + |
| 2041 | + Once you have completed all of your modifications to the local transient |
| 2042 | + collection, you can call `persistent!` to return a persistent version of that |
| 2043 | + data structure." |
| 2044 | + [coll] |
| 2045 | + (if (instance? basilisp.lang.interfaces/IEvolveableCollection coll) |
| 2046 | + (.to-transient coll) |
| 2047 | + (throw |
| 2048 | + (ex-info (str "Object of type " (type coll) " does not implement " |
| 2049 | + "IEvolveableCollection interface") |
| 2050 | + {:coll coll |
| 2051 | + :type (type coll)})))) |
| 2052 | + |
| 2053 | +(defn persistent! |
| 2054 | + "Return a persistent copy of the transient collection `coll` which was created |
| 2055 | + by calling `transient`." |
| 2056 | + [coll] |
| 2057 | + (if (instance? basilisp.lang.interfaces/ITransientCollection coll) |
| 2058 | + (.to-persistent coll) |
| 2059 | + (throw |
| 2060 | + (ex-info (str "Object of type " (type coll) " does not implement " |
| 2061 | + "ITransientCollection interface") |
| 2062 | + {:coll coll |
| 2063 | + :type (type coll)})))) |
| 2064 | + |
| 2065 | +(defn assoc! |
| 2066 | + "Associate keys to values in the transient associative data structure `m`." |
| 2067 | + ([m k v] |
| 2068 | + (.assoc-transient m k v)) |
| 2069 | + ([m k v & kvs] |
| 2070 | + (apply (.-assoc-transient m) k v kvs))) |
| 2071 | + |
| 2072 | +(defn conj! |
| 2073 | + "Conjoin xs to the transient collection `coll`. New elements may be added in |
| 2074 | + different positions depending on the type of `coll`. conj returns the same type |
| 2075 | + as `coll`." |
| 2076 | + ([] (transient [])) |
| 2077 | + ([coll] coll) |
| 2078 | + ([coll & xs] |
| 2079 | + (apply (.-cons-transient coll) xs))) |
| 2080 | + |
| 2081 | +(defn disj! |
| 2082 | + "Return a new version of the transient set `s` without the given elements. If the |
| 2083 | + elements don't exist in `s`, they are ignored." |
| 2084 | + ([s] s) |
| 2085 | + ([s elem] |
| 2086 | + (.disj-transient s elem)) |
| 2087 | + ([s elem & elems] |
| 2088 | + (apply (.-disj-transient s) elem elems))) |
| 2089 | + |
| 2090 | +(defn dissoc! |
| 2091 | + "Return a new version of the transient associative collection `m`` without the |
| 2092 | + given keys. If the keys don't exist in `m`, they are ignored." |
| 2093 | + ([m k] (.dissoc-transient m k)) |
| 2094 | + ([m k & ks] |
| 2095 | + (apply (.-dissoc-transient m) k ks))) |
| 2096 | + |
| 2097 | +(defn pop! |
| 2098 | + "Return a new transient vector without the last element of `coll`. If `coll` is |
| 2099 | + empty, throw an exception." |
| 2100 | + [coll] |
| 2101 | + (.pop-transient coll)) |
| 2102 | + |
2017 | 2103 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
2018 | 2104 | ;; Higher Order and Collection Functions ;;
|
2019 | 2105 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
2634 | 2720 | appears in a map, the rightmost map's value for that key will be taken."
|
2635 | 2721 | [& maps]
|
2636 | 2722 | (when (some identity maps)
|
2637 |
| - (reduce #(conj %1 %2) |
2638 |
| - {} |
2639 |
| - maps))) |
| 2723 | + (persistent! |
| 2724 | + (reduce #(conj! %1 %2) |
| 2725 | + (transient {}) |
| 2726 | + maps)))) |
2640 | 2727 |
|
2641 | 2728 | (defn trampoline
|
2642 | 2729 | "Trampoline f with starting arguments. If f returns an fn, call its return
|
|
4080 | 4167 | associative collection smap, if they exist."
|
4081 | 4168 | [smap coll]
|
4082 | 4169 | (if (vector? coll)
|
4083 |
| - (reduce (fn [res v] |
4084 |
| - (if-let [newv (get smap v)] |
4085 |
| - (conj res newv) |
4086 |
| - res)) |
4087 |
| - [] |
4088 |
| - coll) |
| 4170 | + (persistent! |
| 4171 | + (reduce (fn [res v] |
| 4172 | + (if-let [newv (get smap v)] |
| 4173 | + (conj! res newv) |
| 4174 | + res)) |
| 4175 | + (transient []) |
| 4176 | + coll)) |
4089 | 4177 | (map (fn [v]
|
4090 | 4178 | (if-let [newv (get smap v)]
|
4091 | 4179 | newv
|
|
4095 | 4183 | (defn select-keys
|
4096 | 4184 | "Return a map with only the keys of m which are in ks."
|
4097 | 4185 | [m ks]
|
4098 |
| - (reduce (fn [new-map k] |
4099 |
| - (if (contains? m k) |
4100 |
| - (assoc new-map k (get m k)) |
4101 |
| - new-map)) |
4102 |
| - {} |
4103 |
| - ks)) |
| 4186 | + (persistent! |
| 4187 | + (reduce (fn [new-map k] |
| 4188 | + (if (contains? m k) |
| 4189 | + (assoc! new-map k (get m k)) |
| 4190 | + new-map)) |
| 4191 | + (transient {}) |
| 4192 | + ks))) |
4104 | 4193 |
|
4105 | 4194 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
4106 | 4195 | ;; Destructuring Support ;;
|
|
4845 | 4934 | (reduce (fn [m [method-name arities]]
|
4846 | 4935 | (->> (map rest arities)
|
4847 | 4936 | (apply list `fn)
|
4848 |
| - (assoc m (keyword (name method-name))))) |
4849 |
| - {}))) |
| 4937 | + (assoc! m (keyword (name method-name))))) |
| 4938 | + (transient {})) |
| 4939 | + (persistent!))) |
4850 | 4940 |
|
4851 | 4941 | (defmacro extend-protocol
|
4852 | 4942 | "Extend a Protocol with implementations for multiple types.
|
|
0 commit comments