Skip to content

Commit

Permalink
Added in higher level interface to jvm maps.
Browse files Browse the repository at this point in the history
  • Loading branch information
cnuernber committed Aug 5, 2021
1 parent 04c0592 commit 23260f7
Show file tree
Hide file tree
Showing 7 changed files with 231 additions and 1 deletion.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,5 @@ tech.v3.datatype.main
resources
jdk-16
jdk-16.0.1
library_test
library_test
zulu-jdk
1 change: 1 addition & 0 deletions project.clj
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@
tech.v3.datatype.packing
tech.v3.datatype.ffi.graalvm
tech.v3.parallel.for
tech.v3.datatype.jvm-map
tech.v3.libs.buffered-image
tech.v3.libs.neanderthal]}
:clean-targets [:target-path "docs"]}
Expand Down
2 changes: 2 additions & 0 deletions src/tech/v3/datatype.clj
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@
[tech.v3.datatype.binary-op :as binary-op]
[tech.v3.datatype.binary-pred :as binary-pred]
[tech.v3.datatype.emap :as emap]
;;import in clone for jvm maps
[tech.v3.datatype.jvm-map]
[tech.v3.datatype.export-symbols :refer [export-symbols]])
(:import [tech.v3.datatype.array_buffer ArrayBuffer]
[tech.v3.datatype ListPersistentVector BooleanReader
Expand Down
1 change: 1 addition & 0 deletions src/tech/v3/datatype/base.clj
Original file line number Diff line number Diff line change
Expand Up @@ -578,6 +578,7 @@
(aget ^"[Ljava.lang.Object;" barray chan)))))))



;;Datatype library Object defaults. Here lie dragons.
(extend-type Object
dtype-proto/PElemwiseDatatype
Expand Down
4 changes: 4 additions & 0 deletions src/tech/v3/datatype/datetime.clj
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,10 @@ A general outline is:
local-date-time->local-date
local-date->local-date-time
local-date->days-since-epoch
local-date->epoch-months
epoch-months->local-date
epoch-days->epoch-months
epoch-months->epoch-days
days-since-epoch->local-date
local-date->instant
local-date->zoned-date-time
Expand Down
31 changes: 31 additions & 0 deletions src/tech/v3/datatype/datetime/base.clj
Original file line number Diff line number Diff line change
Expand Up @@ -336,6 +336,37 @@
(instant->local-date instant (utc-zone-id))))


(defn local-date->epoch-months
^long [^LocalDate ld]
(+ (* (- (.getYear ld) 1970) 12)
(unchecked-dec (.getMonthValue ld))))


(def ^{:tag LocalDate} epoch-local-date (milliseconds-since-epoch->local-date 0))


(defn epoch-months->local-date
^LocalDate [^long em]
(.plus epoch-local-date em java.time.temporal.ChronoUnit/MONTHS))


(defn epoch-days->local-date
^LocalDate [^long ed]
(.plus epoch-local-date ed java.time.temporal.ChronoUnit/DAYS))


(defn epoch-days->epoch-months
^long [^long ed]
(-> (days-since-epoch->local-date ed)
(local-date->epoch-months)))


(defn epoch-months->epoch-days
^long [^long em]
(-> (epoch-months->local-date em)
(local-date->days-since-epoch)))


(defn duration
([]
(Duration/ofNanos 0))
Expand Down
190 changes: 190 additions & 0 deletions src/tech/v3/datatype/jvm_map.clj
Original file line number Diff line number Diff line change
@@ -0,0 +1,190 @@
(ns tech.v3.datatype.jvm-map
"Creation and higher-level manipulation for `java.util.HashMap` and
`java.util.concurrent.ConcurrentHashMap`."
(:require [tech.v3.datatype.protocols :as dt-proto])
(:import [java.util Map HashMap Map$Entry Set HashSet]
[java.util.concurrent ConcurrentHashMap]
[java.util.function BiConsumer BiFunction Function])
(:refer-clojure :exclude [hash-map get set]))


(set! *warn-on-reflection* true)


(defn hash-map
(^HashMap []
(HashMap.))
(^HashMap [init-size]
(HashMap. (int init-size))))


(defn set
^Set [] (HashSet. ))


(defn concurrent-hash-map
(^ConcurrentHashMap []
(ConcurrentHashMap.))
(^ConcurrentHashMap [init-size]
(ConcurrentHashMap. (int init-size))))


(defn concurrent-set
(^Set [] (.keySet (concurrent-hash-map))))


(defn put!
"Put a value into a map"
[^Map map k v]
(.put map k v)
map)


(defn add!
"Add a value to a set"
[^Set set k]
(.add set k)
set)


(defn entry-key
"Given a map$Entry, return the key"
[^Map$Entry v]
(when v (.getKey v)))


(defn entry-value
"Given a map$Entry, return the key"
[^Map$Entry v]
(when v (.getValue v)))


(defn get
"Get a value from a map with a potential default. Missing values will be nil otherwise."
([^Map map k]
(.get map k))
([^Map map k default-value]
(.getOrDefault map k default-value)))


(defmacro bi-consumer
"Create a java.util.function.BiConsumer. karg will be the name of the first argument
to the consumer, varg will be the name of the second. Code will be output inline into
the consumer's accept function."
[karg varg code]
`(reify BiConsumer
(accept [this# ~karg ~varg]
~code)))


(defn ->bi-consumer
"Take a thing and return a bi-consumer. If already a bi-consumer return as is,
else calls `(bi-consumer x y (ifn x y))`"
^BiConsumer [ifn]
(if (instance? BiConsumer ifn)
ifn
(bi-consumer x y (ifn x y))))


(defmacro bi-function
"Create a java.util.function.BiFunction. karg will be the name of the first argument,
varg will be the name of the second argument. code will be output inline into the
function's apply function."
[karg varg code]
`(reify BiFunction
(apply [this# ~karg ~varg]
~code)))


(defn ->bi-function
"Take a thing and return a bi-function. If already a bi-function return as is,
else calls `(bi-function x y (ifn x y))`"
^BiFunction [ifn]
(if (instance? BiFunction ifn)
ifn
(bi-function x y (ifn x y))))


(defmacro function
"Create a java.util.function.Function. karg will be the name of the argument,
will be output inline into the function's apply method."
[karg code]
`(reify Function
(apply [this# ~karg]
~code)))


(defn ->function
"Convert an ifn to a java.util.function.Function. If ifn is already a Function,
return with no changes. Else calls `(function x (ifn x))`"
^Function [ifn]
(if (instance? Function ifn)
ifn
(function x (ifn x))))


(defn concurrent-hash-map?
"Return true if this is a concurrent hash map."
[item]
(instance? ConcurrentHashMap item))


(defn foreach!
"Perform an operation for each entry in a map. Returns the op. This method will by
default be serial unless parallel? is true in which case if the item in question
is a concurrent hash map then the parallel version of foreach is used."
([item op & [parallel?]]
(let [consumer (->bi-consumer op)]
(if (and parallel? (concurrent-hash-map? item))
(.forEach ^ConcurrentHashMap item 1 consumer)
(.forEach ^Map item consumer)))
op))


(defn merge-with!
"Merge `rhs` into `lhs` using op to resolve conflicts. Op gets passed two arguments,
`lhs-val` `rhs-val`. If both rhs and lhs are concurrent hash maps then the merge
is performed in parallel.
Returns `lhs`."
[lhs rhs op]
(let [merge-fn (->bi-function op)
foreach-consumer (bi-consumer k v (.merge ^Map lhs k v merge-fn))]
(foreach! rhs foreach-consumer (and (concurrent-hash-map? lhs)
(concurrent-hash-map? rhs))))
lhs)


(defn compute-fn!
"Given a map and a function to call if the value is in the map, return a function that
takes a k and returns the result of calling `(.compute map k (->bi-function val-fn))`.
`val-fn` gets passed the key and existing value (if any)."
[map val-fn]
(let [val-fn (->bi-function val-fn)]
#(.compute ^Map map % val-fn)))


(defn compute-if-absent-fn!
"Given a map and a function to call if the value is not in the map, return a function that
takes a k and returns the result of calling `(.compute map k (->function val-fn))`.
`val-fn` gets passed the key when the value is not in the map."
[map val-fn]
(let [val-fn (->function val-fn)]
#(.computeIfAbsent ^Map map % val-fn)))


(defn compute-if-present-fn!
"Given a map and a function to call if the value is in the map, return a function that
takes a k and returns the result of calling
`(.computeIfPresent map k (->bi-function val-fn))`.
`val-fn` gets passed the existing value and new value is in the map."
[map val-fn]
(let [val-fn (->bi-function val-fn)]
#(.computeIfPresent ^Map map % val-fn)))


(extend-protocol dt-proto/PClone
HashMap
(clone [item] (.clone item))
ConcurrentHashMap
(clone [item] (ConcurrentHashMap. item)))

0 comments on commit 23260f7

Please sign in to comment.