From 9d2b6da1cc7364ecd1228fcc1aeaa5d92d704a7b Mon Sep 17 00:00:00 2001 From: Simon Brooke Date: Wed, 26 Jun 2019 09:37:00 +0100 Subject: [PATCH] Started work on *safe-sparse-operations* Not fully working yet --- src/sparse_array/core.clj | 47 ++++++++++++++++++++++++--------- test/sparse_array/core_test.clj | 34 +++++++++++++++++++----- 2 files changed, 63 insertions(+), 18 deletions(-) diff --git a/src/sparse_array/core.clj b/src/sparse_array/core.clj index b169df8..6906a36 100644 --- a/src/sparse_array/core.clj +++ b/src/sparse_array/core.clj @@ -1,5 +1,7 @@ (ns sparse-array.core) +(def ^:dynamic *safe-sparse-operations* false) + (defn make-sparse-array "Make a sparse array with these `dimensions`. Every member of `dimensions` 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 by this library, else `false`." ([x] - (and - (map? x) - (pos? (:dimensions x)) - (keyword? (:coord x)) - (if - (coll? (:content x)) - (every? - sparse-array? - (map #(x %) (filter integer? (keys x)))) - (= (:content x) :data))))) + (apply + sparse-array? + (cons + x + (cons + (:coord x) + (if + (coll? (:content x)) + (:content x)))))) + ([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 "Return a sparse array like this `array` but with this `value` at these `coordinates`. Returns `nil` if any coordinate is invalid." [array value & coordinates] - (if + (cond + (and *safe-sparse-operations* (sparse-array? array)) + (throw (ex-info "Sparse array expected" {:array array})) (every? #(and (integer? %) (or (zero? %) (pos? %))) coordinates) @@ -49,7 +66,13 @@ (or (array (first coordinates)) (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 "Return the value in this sparse `array` at these `coordinates`." diff --git a/test/sparse_array/core_test.clj b/test/sparse_array/core_test.clj index 815618f..216681a 100644 --- a/test/sparse_array/core_test.clj +++ b/test/sparse_array/core_test.clj @@ -4,7 +4,21 @@ (deftest 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 (testing "get" @@ -84,9 +98,17 @@ [nil nil nil nil nil] [nil nil nil nil "hello"] [nil nil nil "goodbye" nil]] - actual (sparse-to-dense (put - (put - (make-sparse-array :x :y) - "hello" 3 4) - "goodbye" 4 3))] + actual (sparse-to-dense {: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 (= actual expected))))) + +