on master help sign in
Work on docs and simplify/normalize API
ea54e58Evan Czaplicki
libraries/Array.elm+62−74
@@ -1,23 +1,23 @@
1module Array where
1module Array where
2
2
3−{-| A library for immutable arrays. The elements in an array must have the same
3+{-| A library for fast immutable arrays. The elements in an array must have the
4−type. The arrays are implemented in Relaxed Radix Balanced-Trees for fast
4+same type. The arrays are implemented in Relaxed Radix Balanced-Trees for fast
5−reads, updates, and concatenation.
5+reads, updates, and appends.
6
6
7−If you use more then one map or zip function on an array, consider turning it
7+# Creating Arrays
8−into a list before operating on it, and then turning it back into an array.
8+@docs empty, repeat, initialize, fromList
9
9
10# Basics
10# Basics
11−@docs empty, length, get, getMaybe, getSafe
11+@docs length, push, append
12
12
13−# Putting Arrays Together
13+# Get and Set
14−@docs fill, fromList, concat, set, updates, push
14+@docs get, getMaybe, getWithDefault, set
15
15
16# Taking Arrays Apart
16# Taking Arrays Apart
17−@docs toList, toIndexedList, indices, slice
17+@docs toList, toIndexedList, slice
18
18
19−# Mapping, folding, zipping
19+# Mapping and Folding
20−@docs map, indexedMap, foldl, foldr, zip, zipWith
20+@docs map, indexedMap, foldl, foldr
21-}
21-}
22
22
23import Native.Array
23import Native.Array
@@ -27,17 +27,32 @@ import List
27
27
28data Array a = Array
28data Array a = Array
29
29
30−{-| Fills an array with a given length and a default element.
30+-- TODO: make this a native function
31+{-| Initialize an array. `initialize n f` creates an array of length `n` with
32+the element at index `i` initialized to the result of `(f i)`.
31
33
32− fill 3 5 == fromList [5,5,5]
34+ initialize 4 id == fromList [0,1,2,3]
35+ initialize 4 (\n -> n*n) == fromList [0,1,4,9]
36+ initialize 4 (always 0) == fromList [0,0,0,0]
33-}
37-}
34−fill : Int -> a -> Array a
38+initialize : Int -> (Int -> a) -> Array a
39+initialize n initializer =
35−fill len e = fromList <| List.map (always e) [1..len]
40+ fromList <| List.map initializer [ 0 .. n - 1 ]
41+
42+{-| Creates an array with a given length, filled with a default element.
43+
44+ repeat 5 0 == fromList [0,0,0,0,0]
45+ repeat 3 "cat" == fromList ["cat","cat","cat"]
46+
47+Notice that `repeat 3 x` is the same as `initialize 3 (always x)`.
48+-}
49+repeat : Int -> a -> Array a
50+repeat n e = initialize n (always e)
36
51
37-- TODO: make this a native function.
52-- TODO: make this a native function.
38{-| Create an array from a list. -}
53{-| Create an array from a list. -}
39fromList : [a] -> Array a
54fromList : [a] -> Array a
40−fromList = List.foldl (Native.Array.push) Native.Array.empty
55+fromList xs = List.foldl Native.Array.push Native.Array.empty xs
41
56
42{-| Create a list of elements from an array.
57{-| Create a list of elements from an array.
43
58
@@ -46,24 +61,19 @@ fromList = List.foldl (Native.Array.push) Native.Array.empty
46toList : Array a -> [a]
61toList : Array a -> [a]
47toList = Native.Array.toList
62toList = Native.Array.toList
48
63
49−{-| Create a list of the possible indices of an array.
50−
51− indices (fromList [3,5,8] == [0,1,2])
52−-}
53−indices : Array a -> [Int]
54−indices a = [0..Native.Array.length a - 1]
55−
56-- TODO: make this a native function.
64-- TODO: make this a native function.
57−{-| Create a list of tuples (Index, Element) from an array.
65+{-| Create an indexed list from an array. Each element of the array will be
66+paired with its index.
58
67
59− toIndexedList (fromList [3,5,8]) == [(0,3), (1,5), (2,8)]
68+ toIndexedList (fromList ["cat","dog"]) == [(0,"cat"), (1,"dog")]
60-}
69-}
61toIndexedList : Array a -> [(Int, a)]
70toIndexedList : Array a -> [(Int, a)]
71+toIndexedList array =
62−toIndexedList a = List.zip (indices a) (Native.Array.toList a)
72+ List.zip [ 0 .. Native.Array.length array - 1 ] (Native.Array.toList array)
63
73
64{-| Apply a function on every element in an array.
74{-| Apply a function on every element in an array.
65
75
66− map (\x -> x*x) (fromList [1,2,3]) == fromList [1,4,9]
76+ map sqrt (fromList [1,4,9]) == fromList [1,2,3]
67-}
77-}
68map : (a -> b) -> Array a -> Array b
78map : (a -> b) -> Array a -> Array b
69map = Native.Array.map
79map = Native.Array.map
@@ -77,35 +87,18 @@ indexedMap = Native.Array.indexedMap
77
87
78{-| Reduce an array from the left.
88{-| Reduce an array from the left.
79
89
80− foldl (+) 0 (fill 3 5) == 15
90+ foldl (::) [] (fromList [1,2,3]) == [3,2,1]
81-}
91-}
82foldl : (a -> b -> b) -> b -> Array a -> b
92foldl : (a -> b -> b) -> b -> Array a -> b
83foldl = Native.Array.foldl
93foldl = Native.Array.foldl
84
94
85{-| Reduce an array from the right.
95{-| Reduce an array from the right.
86
96
87− foldr (::) [] (fromList [1,2,3]) == [3,2,1]
97+ foldr (+) 0 (repeat 3 5) == 15
88-}
98-}
89foldr : (a -> b -> b) -> b -> Array a -> b
99foldr : (a -> b -> b) -> b -> Array a -> b
90foldr = Native.Array.foldr
100foldr = Native.Array.foldr
91
101
92−{-| Zip the elements of two arrays via a tuple into a new array. If one array is
93−longer, the extra elements are dropped.
94−
95− zip (fromList [1,2,3,4]) (fromList [0,0,0]) = fromList [(1,0), (2,0), (3,0)]
96−-}
97−zip : Array a -> Array b -> Array (a,b)
98−zip = zipWith (,)
99−
100−{-| Zips the elements of two arrays via a function into a new array. If one array
101−is longer, the extra elements are dropped.
102−
103− zipWith (+) (fill 3 5) (fill 5 8) == fill 3 13
104−-}
105−zipWith : (a -> b -> c) -> Array a -> Array b -> Array c
106−zipWith f a b =
107− fromList <| List.zipWith f (Native.Array.toList a) (Native.Array.toList b)
108−
109{-| Return an empty array.
102{-| Return an empty array.
110
103
111 length empty == 0
104 length empty == 0
@@ -121,7 +114,7 @@ push : a -> Array a -> Array a
121push = Native.Array.push
114push = Native.Array.push
122
115
123{-| Return the element at the index. Breaks, if index is out of range. If the
116{-| Return the element at the index. Breaks, if index is out of range. If the
124−array length is unkown, use safeGet oder getWithDefault.
117+array length is unkown, use withDefaultGet oder getWithDefault.
125
118
126 get 2 (A.fromList [3,2,1]) == 1
119 get 2 (A.fromList [3,2,1]) == 1
127-}
120-}
@@ -130,46 +123,41 @@ get = Native.Array.get
130
123
131{-| Return Just the element at the index or Nothing if the index is out of range.
124{-| Return Just the element at the index or Nothing if the index is out of range.
132
125
133− getMaybe 2 (A.fromList [3,2,1]) == Just 2
126+ getMaybe 2 (fromList [3,2,1]) == Just 2
134− getMaybe 5 (A.fromList [3,2,1]) == Nothing
127+ getMaybe 5 (fromList [3,2,1]) == Nothing
135-}
128-}
136getMaybe : Int -> Array a -> Maybe a
129getMaybe : Int -> Array a -> Maybe a
130+getMaybe i array =
137−getMaybe i array = if Native.Array.length array > i
131+ if Native.Array.length array > i
138− then Just (Native.Array.get i array)
132+ then Just (Native.Array.get i array)
139− else Nothing
133+ else Nothing
140
134
141{-| Get the element at the index. If the index is out of range, the given default
135{-| Get the element at the index. If the index is out of range, the given default
142element is returned.
136element is returned.
143
137
144− getSafe 0 2 (A.fromList [3,2,1]) == 1
138+ getWithDefault 0 2 (fromList [3,2,1]) == 1
145− getSafe 0 5 (A.fromList [3,2,1]) == 0
139+ getWithDefault 0 5 (fromList [3,2,1]) == 0
146-}
140-}
147−getSafe : a -> Int -> Array a -> a
141+getWithDefault : a -> Int -> Array a -> a
142+getWithDefault default i array =
148−getSafe default i array = if Native.Array.length array > i
143+ if Native.Array.length array > i
149− then Native.Array.get i array else default
144+ then Native.Array.get i array
145+ else default
150
146
151−{-| Set the element at the index. Returns the updated array, or if the index is
147+{-| Set the element at a particular index. Returns an updated array.
152−out of range, the unaltered array.
148+If the index is out of range, the array is unaltered.
153
149
154 set 1 7 (fromList [1,2,3]) == fromList [1,7,3]
150 set 1 7 (fromList [1,2,3]) == fromList [1,7,3]
155-}
151-}
156set : Int -> a -> Array a -> Array a
152set : Int -> a -> Array a -> Array a
157set = Native.Array.set
153set = Native.Array.set
158
154
159−{-| Update an array with a a list tuples, wherein the first Int is the index.
160−
161− updates [(1,7),(2,8)] (fill 3 1) == fromList [1,7,8]
162−-}
163−updates : [(Int, a)] -> Array a -> Array a
164−updates us array = List.foldl (uncurry Native.Array.set) array us
165−
166{-| Slice an array given a range. The selection is inclusive, so the last
155{-| Slice an array given a range. The selection is inclusive, so the last
167element in the selection will also be in the new array. This may change in the
156element in the selection will also be in the new array. This may change in the
168−future.
169−You can select from the end by giving a negative Int.
157+future. You can select from the end by giving a negative Int.
170
158
171− slice 1 2 (fromList [0,1,2,3,4]) == fromList [1,2]
159+ slice 1 2 (fromList [0,1,2,3,4]) == fromList [1,2]
172− slice 1 -2 (fromList [0,1,2,3,4]) == fromList [1,2,3]
160+ slice 1 -2 (fromList [0,1,2,3,4]) == fromList [1,2,3]
173 slice -3 -2 (fromList [0,1,2,3,4]) == fromList [2,3]
161 slice -3 -2 (fromList [0,1,2,3,4]) == fromList [2,3]
174-}
162-}
175slice : Int -> Int -> Array a -> Array a
163slice : Int -> Int -> Array a -> Array a
@@ -182,9 +170,9 @@ slice = Native.Array.slice
182length : Array a -> Int
170length : Array a -> Int
183length = Native.Array.length
171length = Native.Array.length
184
172
185−{-| Concat two arrays to a new one.
173+{-| Append two arrays to a new one.
186
174
187− concat (fill 3 1) (fill 4 2) == fromList [1,1,1,2,2,2,2]
175+ append (array 2 42) (array 3 81) == fromList [42,42,81,81,81]
188-}
176-}
189−concat : Array a -> Array a -> Array a
177+append : Array a -> Array a -> Array a
190−concat = Native.Array.concat
178+append = Native.Array.append
libraries/Native/Array.js+18−18
@@ -232,15 +232,15 @@ Elm.Native.Array.make = function(elm) {
232 return newA;
232 return newA;
233 }
233 }
234
234
235− // Concats two trees.
235+ // Appends two trees.
236− // TODO: Add support for concatting trees of different sizes. Current
236+ // TODO: Add support for appending trees of different sizes. Current
237− // behavior will just rise the lower tree and then concat them.
237+ // behavior will just rise the lower tree and then append them.
238− function concat(a, b) {
238+ function append(a,b) {
239− if (b.height > a.height) { return concat(parentise(a, b.height), b); }
239+ if (b.height > a.height) { return append(parentise(a, b.height), b); }
240− if (a.height > b.height) { return concat(a, parentise(b, a.height)); }
240+ if (a.height > b.height) { return append(a, parentise(b, a.height)); }
241− if (a.height == 0) { return concat(parentise(a, 1), parentise(b, 1)); }
241+ if (a.height == 0) { return append(parentise(a, 1), parentise(b, 1)); }
242−
242+
243− var c = concat_(a, b);
243+ var c = append_(a, b);
244 if (c[1].table.length > 0) {
244 if (c[1].table.length > 0) {
245 return siblise(c[0], c[1]);
245 return siblise(c[0], c[1]);
246 } else {
246 } else {
@@ -249,9 +249,9 @@ Elm.Native.Array.make = function(elm) {
249 }
249 }
250
250
251 // Returns an array of two nodes. The second node _may_ be empty. This case
251 // Returns an array of two nodes. The second node _may_ be empty. This case
252− // needs to be handled by the function, that called concat_. May be only
252+ // needs to be handled by the function, that called append_. May be only
253 // called for trees with an minimal height of 1.
253 // called for trees with an minimal height of 1.
254− function concat_(a, b) {
254+ function append_(a, b) {
255 if (a.height == 1) {
255 if (a.height == 1) {
256 // Check if balancing is needed and return based on that.
256 // Check if balancing is needed and return based on that.
257 var toRemove = calcToRemove(a, b);
257 var toRemove = calcToRemove(a, b);
@@ -262,18 +262,18 @@ Elm.Native.Array.make = function(elm) {
262 return shuffle(a, b, toRemove);
262 return shuffle(a, b, toRemove);
263 }
263 }
264
264
265− var concated = concat_(botRight(a), botLeft(b));
265+ var appended = append_(botRight(a), botLeft(b));
266 a = nodeCopy(a), b = nodeCopy(b);
266 a = nodeCopy(a), b = nodeCopy(b);
267
267
268 // Adjust the bottom right side of the new tree.
268 // Adjust the bottom right side of the new tree.
269− a.table[a.table.length - 1] = concated[0];
269+ a.table[a.table.length - 1] = appended[0];
270− a.lengths[a.lengths.length - 1] = length(concated[0])
270+ a.lengths[a.lengths.length - 1] = length(appended[0])
271 a.lengths[a.lengths.length - 1] += a.lengths.length > 1 ? a.lengths[a.lengths.length - 2] : 0;
271 a.lengths[a.lengths.length - 1] += a.lengths.length > 1 ? a.lengths[a.lengths.length - 2] : 0;
272
272
273 // Adjust the bottom left side of the new tree.
273 // Adjust the bottom left side of the new tree.
274− if (concated[1].table.length > 0) {
274+ if (appended[1].table.length > 0) {
275− b.table[0] = concated[1];
275+ b.table[0] = appended[1];
276− b.lengths[0] = length(concated[1]);
276+ b.lengths[0] = length(appended[1]);
277 for (var i = 1, len = length(b.table[0]); i < b.lengths.length; i++) {
277 for (var i = 1, len = length(b.table[0]); i < b.lengths.length; i++) {
278 len += length(b.table[i]);
278 len += length(b.table[i]);
279 b.lengths[i] = len;
279 b.lengths[i] = len;
@@ -475,7 +475,7 @@ Elm.Native.Array.make = function(elm) {
475 Elm.Native.Array.values = {
475 Elm.Native.Array.values = {
476 empty:empty,
476 empty:empty,
477 toList:toList,
477 toList:toList,
478− concat:F2(concat),
478+ append:F2(append),
479 push:F2(push),
479 push:F2(push),
480 slice:F3(slice),
480 slice:F3(slice),
481 get:F2(get),
481 get:F2(get),