Merge pull request #442 from GrayJack/safe-array

Make Array module safer
This commit is contained in:
Erik Svedäng 2019-05-21 12:11:38 +02:00 committed by GitHub
commit 4f61d83730
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 67 additions and 49 deletions

View File

@ -67,6 +67,7 @@ To build this example, save it to a file called 'example.carp' and load it with
* Reini Urban
* Jonas Granquist
* Joel Kaasinen ([@opqdonut](https://github.com/opqdonut))
* Eric Shimizu Karbstein ([@GrayJack](https://github.com/GrayJack))
Are you missing from the contributors list? Please send a pull request!

View File

@ -41,13 +41,15 @@ It will sum the previous sum with each new value, starting at `0`.")
(break))))
res))
(doc find "finds an element in `a` that matches the function `f`.")
(doc find "finds an element in `a` that matches the function `f` and wraps it in a `Just`.
If it doesnt find an element, `Nothing` will be returned.")
(defn find [f a]
(let-do [res (zero)]
(let-do [res (Maybe.Nothing)]
(for [i 0 (length a)]
(when (~f (nth a i))
(do
(set! res @(nth a i))
(set! res (Maybe.Just @(nth a i)))
(break))))
res))
@ -108,43 +110,44 @@ Returns `Nothing` if the array is empty.")
(defn /= [a b]
(not (= (the (Ref (Array a)) a) b)))
; TODO unsafe!
(doc maximum "gets the maximum in an array (elements must support `<`).")
(doc maximum "gets the maximum in an array (elements must support `<`) and wraps it in a `Just`.
If the array is empty, it returns `Nothing`.")
(defn maximum [xs]
(let [result (unsafe-first xs)
n (length xs)]
(do
(if (empty? xs)
(Maybe.Nothing)
(let-do [result (nth xs 0)
n (length xs)]
(for [i 1 n]
(let [x @(nth xs i)]
(if (< &result &x)
(set! result x)
())))
result)))
(let [x (nth xs i)]
(when (< result x)
(set! result x))))
(Maybe.Just @result))))
; TODO unsafe!
(doc minimum "gets the maximum in an array (elements must support `>`).")
(doc minimum "gets the minimum in an array (elements must support `>`) and wraps it in a `Just`.
If the array is empty, returns `Nothing`")
(defn minimum [xs]
(let [result (unsafe-first xs)
n (length xs)]
(do
(if (empty? xs)
(Maybe.Nothing)
(let-do [result (nth xs 0)
n (length xs)]
(for [i 1 n]
(let [x @(nth xs i)]
(if (> &result &x)
(set! result x)
())))
result)))
(let [x (nth xs i)]
(when (> result x)
(set! result x))))
(Maybe.Just @result))))
(doc sum "ums an array (elements must support `+` and `zero`).")
(doc sum "sums an array (elements must support `+` and `zero`).")
(defn sum [xs]
(Array.reduce &(fn [x y] (+ x @y)) (zero) xs))
(doc subarray "gets a subarray from `start-index` to `end-index`.")
(defn subarray [xs start-index end-index]
(let [result []]
(do
(for [i start-index end-index]
(set! result (push-back result @(nth xs i))))
result)))
(let-do [result []]
(for [i start-index end-index]
(set! result (push-back result @(nth xs i))))
result))
(doc prefix-array "gets a prefix array to `end-index`.")
(defn prefix-array [xs end-index]
@ -166,13 +169,15 @@ Returns `Nothing` if the array is empty.")
(set! j (Int.dec j))))
a))
(doc index-of "gets the index of element `e` in an array.")
(doc index-of "gets the index of element `e` in an array and wraps it on a `Just`.
If the element is not found, returns `Nothing`")
(defn index-of [a e]
(let-do [idx -1]
(let-do [idx (Maybe.Nothing)]
(for [i 0 (length a)]
(when (= (nth a i) e)
(do
(set! idx i)
(set! idx (Maybe.Just i))
(break))))
idx))

View File

@ -82,7 +82,7 @@
(= n 1) @(Array.nth data 0)
(let [x @(Array.nth data (/ n 2)) ; else
l (- x (/ (from-int interval) 2.0))
cf (Array.index-of data &x)
cf (Maybe.from (Array.index-of data &x) -1)
f (Array.element-count data &x)]
(+ l (/ (* (from-int interval) (- (/ (from-int n) 2.0) (from-int cf)))
(from-int f)))))))
@ -177,8 +177,8 @@
(defn summary [samples]
(Summary.init
(Array.sum samples)
(Array.minimum samples)
(Array.maximum samples)
(Maybe.from (Array.minimum samples) 0.0)
(Maybe.from (Array.maximum samples) 0.0)
(mean samples)
(median samples)
(variance samples)

View File

@ -36,4 +36,8 @@
(doc reverse "reverses a `Pair` `p` such that its first member is its second member and vice versa.")
(defn reverse [p]
(Pair.init @(Pair.b p) @(Pair.a p)))
)
(doc zero "return default values of the type inside `Pair`")
(defn zero []
(Pair.init (zero) (zero)))
)

View File

@ -76,21 +76,29 @@
&(reverse [1 2 3])
"reverse works as expected")
(assert-equal test
10
(maximum &(range 1 10 1))
&(Maybe.Just 10)
&(maximum &(range 1 10 1))
"maximum works as expected")
(assert-equal test
1
(minimum &(range 1 10 1))
&(Maybe.Just 1)
&(minimum &(range 1 10 1))
"minimum works as expected")
(assert-equal test
&(Pair.init 2 1)
&(Maybe.Just (Pair.init 2 1))
&(maximum &[(Pair.init 1 3) (Pair.init 2 1) (Pair.init 2 0)])
"maximum works on pairs")
(assert-equal test
&(Pair.init 1 3)
&(Maybe.Just (Pair.init 1 3))
&(minimum &[(Pair.init 1 3) (Pair.init 2 1) (Pair.init 2 0)])
"minimum works on pairs")
(assert-equal test
&(Maybe.Just 3)
&(index-of &[1 2 3 4] &4)
"index-of works as expected when element is in the array")
(assert-equal test
&(Maybe.Nothing)
&(index-of &[1 2 3 4] &7)
"index-of works as expected when element is not in the array")
(assert-equal test
55
(sum &(range 1 10 1))
@ -247,12 +255,12 @@
(all? &(fn [x] (= 0 @x)) &(range 10 1 -1))
"all? works as expected II")
(assert-equal test
3
(find &(fn [x] (= 3 @x)) &(range 1 10 1))
&(Maybe.Just 3)
&(find &(fn [x] (= 3 @x)) &(range 1 10 1))
"find works as expected I")
(assert-equal test
0
(find &(fn [x] (= 0 @x)) &(range 1 10 1))
&(Maybe.Nothing)
&(find &(fn [x] (= 0 @x)) &(range 1 10 1))
"find works as expected II")
(assert-equal test
&(Maybe.Nothing)

View File

@ -231,11 +231,11 @@
(defn array-maximum []
(let [xs [1 7 2 9 3 8 4 6 5]]
(assert (= 9 (maximum &xs)))))
(assert (= &(Maybe.Just 9) &(maximum &xs)))))
(defn array-minimum []
(let [xs [8 4 6 5 1 7 2 9 3]]
(assert (= 1 (minimum &xs)))))
(assert (= &(Maybe.Just 1) &(minimum &xs)))))
(defn array-sum []
(let [xs [10 20 30 40 50]]
@ -252,7 +252,7 @@
(defn array-index-of []
(let [xs [@"a" @"b" @"c" @"d" @"e"]]
(assert (= 2 (Array.index-of &xs "c")))))
(assert (= &(Maybe.Just 2) &(Array.index-of &xs "c")))))
(defn array-element-count []
(let [xs [@"a" @"b" @"a" @"a" @"b"]]