Skip to content

Commit 55aa92f

Browse files
committed
feat: IArray interface
1 parent febf288 commit 55aa92f

File tree

2 files changed

+61
-0
lines changed

2 files changed

+61
-0
lines changed

src/gen/array.cljc

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
(ns gen.array
2+
"Protocol and API methods for converting types to and from an array of values.
3+
4+
These functions are useful for converting nested, hierarchical data structures
5+
into ordered vectors without structure and recovering them back."
6+
(:refer-clojure :exclude [to-array]))
7+
8+
(defprotocol IArray
9+
(to-array [x] "Returns a flat vector representation of `x`.")
10+
(-from-array [x a start-idx]
11+
"Given some `x`, an input vector `a` and a starting index `start-idx`,
12+
returns a pair of
13+
14+
- the number of elements read off of the vector
15+
- an instance of the same type and shape as `x`, with its leaves populated by
16+
values from `a` beginning at `start-idx`."))
17+
18+
(defn from-array
19+
"Given some structured input `m` and an input vector `xs`, returns an instance
20+
of the same type and shape as `m`, with its leaves populated by values from
21+
`xs`.
22+
23+
Throws an exception if the count of `xs` doesn't match the number of leaves in
24+
`m`."
25+
[m xs]
26+
(let [[n ret] (-from-array m xs 0)]
27+
(if (= n (count xs))
28+
ret
29+
(throw (ex-info "Dimension mismatch: " {:xs xs :n n})))))

test/gen/array_test.cljc

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
(ns gen.array-test
2+
"Tests for the [[gen.array]] namespace and the various base implementations
3+
that live there."
4+
(:require [clojure.test :refer [deftest is]]
5+
[clojure.test.check.generators :as gen]
6+
[com.gfredericks.test.chuck.clojure-test :refer [checking]]
7+
[gen.array :as array]))
8+
9+
(defn array-round-trip [m]
10+
(is (= m
11+
(->> (array/to-array m)
12+
(array/from-array m)))
13+
"entry round-trips through array."))
14+
15+
;; Wrapper for a non-collection, single element for testing.
16+
(defrecord Element [v]
17+
array/IArray
18+
(to-array [_] [v])
19+
(-from-array [_ xs idx]
20+
[1 (Element. (nth xs idx))]))
21+
22+
(deftest from-array-test
23+
(checking "Element round-trips through array" 100
24+
[elem (gen/fmap ->Element gen/any-equatable)]
25+
(array-round-trip elem))
26+
27+
(checking "failure on incorrect array source" 100
28+
[elem (gen/fmap ->Element gen/any-equatable)]
29+
(is (thrown?
30+
#?(:clj clojure.lang.ExceptionInfo :cljs js/Error)
31+
(array/from-array elem [1 2 3]))
32+
"input array is too big!")))

0 commit comments

Comments
 (0)