Started work on *safe-sparse-operations*

Not fully working yet
This commit is contained in:
Simon Brooke 2019-06-26 09:37:00 +01:00
parent d430937c56
commit 9d2b6da1cc
2 changed files with 63 additions and 18 deletions

View file

@ -1,5 +1,7 @@
(ns sparse-array.core) (ns sparse-array.core)
(def ^:dynamic *safe-sparse-operations* false)
(defn make-sparse-array (defn make-sparse-array
"Make a sparse array with these `dimensions`. Every member of `dimensions` "Make a sparse array with these `dimensions`. Every member of `dimensions`
must be a keyword; otherwise, `nil` will be returned." must be a keyword; otherwise, `nil` will be returned."
@ -18,22 +20,37 @@
"`true` if `x` is a sparse array conforming to the conventions established "`true` if `x` is a sparse array conforming to the conventions established
by this library, else `false`." by this library, else `false`."
([x] ([x]
(and (apply
(map? x) sparse-array?
(pos? (:dimensions x)) (cons
(keyword? (:coord x)) x
(if (cons
(coll? (:content x)) (:coord x)
(every? (if
sparse-array? (coll? (:content x))
(map #(x %) (filter integer? (keys x)))) (:content x))))))
(= (:content x) :data))))) ([x & axes]
(and
(map? x)
(pos? (:dimensions x))
(keyword? (:coord x))
(= (:coord x) (first axes))
(if
(rest axes)
(and
(= (:content x) (rest axes))
(every?
sparse-array?
(map #(x %) (filter integer? (keys x)))))
(= (:content x) :data)))))
(defn put (defn put
"Return a sparse array like this `array` but with this `value` at these "Return a sparse array like this `array` but with this `value` at these
`coordinates`. Returns `nil` if any coordinate is invalid." `coordinates`. Returns `nil` if any coordinate is invalid."
[array value & coordinates] [array value & coordinates]
(if (cond
(and *safe-sparse-operations* (sparse-array? array))
(throw (ex-info "Sparse array expected" {:array array}))
(every? (every?
#(and (integer? %) (or (zero? %) (pos? %))) #(and (integer? %) (or (zero? %) (pos? %)))
coordinates) coordinates)
@ -49,7 +66,13 @@
(or (or
(array (first coordinates)) (array (first coordinates))
(apply make-sparse-array (:content array))) (apply make-sparse-array (:content array)))
(cons value (rest coordinates)))))))) (cons value (rest coordinates))))))
*safe-sparse-operations*
(throw
(ex-info
"Coordinates must be zero or positive integers"
{:coordinates coordinates
:invalid (remove integer? coordinates)}))))
(defn get (defn get
"Return the value in this sparse `array` at these `coordinates`." "Return the value in this sparse `array` at these `coordinates`."

View file

@ -4,7 +4,21 @@
(deftest creation-and-testing (deftest creation-and-testing
(testing "Creation and testing." (testing "Creation and testing."
(is (sparse-array? (make-sparse-array :x :y :z))))) (is (sparse-array? (make-sparse-array :x :y :z)))
(is (sparse-array? {:dimensions 2,
:coord :x,
:content '(:y),
3 {:dimensions 1,
:coord :y,
:content :data,
4 "hello"},
4 {:dimensions 1,
:coord :y,
:content :data,
3 "goodbye"}}))
(is-not (sparse-array? []))
(is-not (sparse-array? "hello"))
))
(deftest put-and-get (deftest put-and-get
(testing "get" (testing "get"
@ -84,9 +98,17 @@
[nil nil nil nil nil] [nil nil nil nil nil]
[nil nil nil nil "hello"] [nil nil nil nil "hello"]
[nil nil nil "goodbye" nil]] [nil nil nil "goodbye" nil]]
actual (sparse-to-dense (put actual (sparse-to-dense {:dimensions 2,
(put :coord :x,
(make-sparse-array :x :y) :content '(:y),
"hello" 3 4) 3 {:dimensions 1,
"goodbye" 4 3))] :coord :y,
:content :data,
4 "hello"},
4 {:dimensions 1,
:coord :y,
:content :data,
3 "goodbye"}})]
(is (= actual expected))))) (is (= actual expected)))))