Skip to content

Commit 7c804e3

Browse files
committed
Merge pull request #180 from CodaFi/an-array-of-simplifications
An Array of Simplifications
2 parents 796132a + 4700c22 commit 7c804e3

File tree

4 files changed

+101
-67
lines changed

4 files changed

+101
-67
lines changed

Swiftz/ArrayExt.swift

Lines changed: 68 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@ public enum ArrayMatcher<A> {
1515

1616
/// Destructures a list into its constituent parts.
1717
///
18-
/// If the given list is empty, this function returns .Empty. If the list is non-empty, this
19-
/// function returns .Cons(hd, tl)
18+
/// If the given list is empty, this function returns .Nil. If the list is non-empty, this
19+
/// function returns .Cons(head, tail)
2020
public func match<T>(l : [T]) -> ArrayMatcher<T> {
2121
if l.count == 0 {
2222
return .Nil
@@ -48,6 +48,32 @@ public func tail<A>(l : [A]) -> Optional<[A]> {
4848
}
4949
}
5050

51+
/// Takes, at most, a specified number of elements from a list and returns that sublist.
52+
///
53+
/// take(3, from: [1,2]) == [1,2]
54+
/// take(-1, from: [1,2]) == []
55+
/// take(0, from: [1,2]) == []
56+
public func take<A>(n : Int, from list : [A]) -> [A] {
57+
if n <= 0 {
58+
return []
59+
}
60+
61+
return Array(list[0 ..< min(n, list.count)])
62+
}
63+
64+
/// Drops, at most, a specified number of elements from a list and returns that sublist.
65+
///
66+
/// drop(3, from: [1,2]) == []
67+
/// drop(-1, from: [1,2]) == [1,2]
68+
/// drop(0, from: [1,2]) == [1,2]
69+
public func drop<A>(n : Int, from list : [A]) -> [A] {
70+
if n <= 0 {
71+
return list
72+
}
73+
74+
return Array(list[min(n, list.count) ..< list.count])
75+
}
76+
5177
/// Adds an element to the front of a list.
5278
public func cons<T>(lhs : T, var rhs : [T]) -> [T] {
5379
rhs.insert(lhs, atIndex: 0)
@@ -121,15 +147,8 @@ public func find<T>(list : [T], f : (T -> Bool)) -> T? {
121147
/// splitAt(3, [1,2,3]) == ([1,2,3],[])
122148
/// splitAt(4, [1,2,3]) == ([1,2,3],[])
123149
/// splitAt(0, [1,2,3]) == ([],[1,2,3])
124-
public func splitAt<T>(index : Int, list : [T]) -> ([T], [T]) {
125-
switch index {
126-
case 0..<list.count:
127-
return (Array(list[0..<index]), Array(list[index..<list.count]))
128-
case list.count...Int.max:
129-
return (list, [T]())
130-
default:
131-
return ([T](), [T]())
132-
}
150+
public func splitAt<T>(n : Int, list : [T]) -> ([T], [T]) {
151+
return (take(n, from: list), drop(n, from: list))
133152
}
134153

135154
/// Takes a separator and a list and intersperses that element throughout the list.
@@ -151,7 +170,7 @@ public func intersperse<T>(item : T, list : [T]) -> [T] {
151170
return list
152171
} else {
153172
var array = Array([list[0]])
154-
array += prependAll(item, Array(list[1..<list.count]))
173+
array += prependAll(item, tail(list)!)
155174
return Array(array)
156175
}
157176
}
@@ -275,32 +294,28 @@ public func intercalate<A>(list : [A], nested : [[A]]) -> [A] {
275294
///
276295
/// span(list, p) == (takeWhile(list, p), dropWhile(list, p))
277296
public func span<A>(list : [A], p : (A -> Bool)) -> ([A], [A]) {
278-
switch list.count {
279-
case 0:
280-
return (list, list)
281-
case 1...list.count where p(list.first!):
282-
let first = list.first!
283-
let (ys,zs) = span(Array(list[1..<list.count]), p)
284-
let f = concat(lhs: [first])(rhs: ys)
285-
return (f,zs)
286-
default:
297+
switch match(list) {
298+
case .Nil:
299+
return ([], [])
300+
case .Cons(let x, let xs):
301+
if p(x) {
302+
let (ys, zs) = span(xs, p)
303+
return (cons(x, ys), zs)
304+
}
287305
return ([], list)
288306
}
289307
}
290308

291309
/// Takes a list and groups its arguments into sublists of duplicate elements found next to each
292310
/// other according to an equality predicate.
293-
public func groupBy<A>(list : [A], p : (A -> A -> Bool)) -> [[A]] {
294-
switch list.count {
295-
case 0:
296-
return []
297-
case 1...list.count:
298-
let first = list.first!
299-
let (ys,zs) = span(Array(list[1..<list.count]), p(first))
300-
let x = [concat(lhs: [first])(rhs: ys)]
301-
return concat(lhs: x)(rhs: groupBy(zs, p))
302-
default:
311+
public func groupBy<A>(list : [A], p : A -> A -> Bool) -> [[A]] {
312+
switch match(list) {
313+
case .Nil:
303314
return []
315+
case .Cons(let x, let xs):
316+
let (ys, zs) = span(xs, p(x))
317+
let l = cons(x, ys)
318+
return cons(l, groupBy(zs, p))
304319
}
305320
}
306321

@@ -309,40 +324,42 @@ public func groupBy<A>(list : [A], p : (A -> A -> Bool)) -> [[A]] {
309324
/// other.
310325
///
311326
/// group([0, 1, 1, 2, 3, 3, 4, 5, 6, 7, 7]) == [[0], [1, 1], [2], [3, 3], [4], [5], [6], [7, 7]]
312-
public func group<A:Equatable>(list : [A]) -> [[A]] {
327+
public func group<A : Equatable>(list : [A]) -> [[A]] {
313328
return groupBy(list, { a in { b in a == b } })
314329
}
315330

316331
/// Returns a list of the first elements that do not satisfy a predicate until that predicate
317332
/// returns false.
318333
///
319-
/// dropWhile([1, 2, 3, 4, 5, 1, 2, 3]){ <3 } == [3,4,5,1,2,3]
320-
/// dropWhile([1, 2, 3]){ <9 } == []
321-
/// dropWhile([1, 2, 3]){ <0 } == [1,2,3]
334+
/// dropWhile([1, 2, 3, 4, 5, 1, 2, 3], <3) == [3,4,5,1,2,3]
335+
/// dropWhile([1, 2, 3], <9) == []
336+
/// dropWhile([1, 2, 3], <0) == [1,2,3]
322337
public func dropWhile<A>(list : [A], p : A -> Bool) -> [A] {
323-
switch list.count {
324-
case 0:
325-
return list
326-
case 1...list.count where p(list.first!):
327-
return dropWhile(Array(list[1..<list.count]), p)
328-
default:
338+
switch match(list) {
339+
case .Nil:
340+
return []
341+
case .Cons(let x, let xs):
342+
if p(x) {
343+
return dropWhile(xs, p)
344+
}
329345
return list
330346
}
331347
}
332348

333349
/// Returns a list of the first elements that satisfy a predicate until that predicate returns
334350
/// false.
335351
///
336-
/// takeWhile([1, 2, 3, 4, 1, 2, 3, 4]){ <3 } == [1, 2]
337-
/// takeWhile([1,2,3]){ <9 } == [1, 2, 3]
338-
/// takeWhile([1,2,3]){ <0 } == []
339-
public func takeWhile<A>(list: [A], p: A -> Bool) -> [A] {
340-
switch list.count {
341-
case 0:
342-
return list
343-
case 1...list.count where p(list.first!):
344-
return concat(lhs: [list.first!])(rhs: takeWhile(Array(list[1..<list.count]), p))
345-
default:
352+
/// takeWhile([1, 2, 3, 4, 1, 2, 3, 4], <3) == [1, 2]
353+
/// takeWhile([1,2,3], <9) == [1, 2, 3]
354+
/// takeWhile([1,2,3], <0) == []
355+
public func takeWhile<A>(list : [A], p : A -> Bool) -> [A] {
356+
switch match(list) {
357+
case .Nil:
358+
return []
359+
case .Cons(let x, let xs):
360+
if p(x) {
361+
return cons(x, takeWhile(xs, p))
362+
}
346363
return []
347364
}
348365
}

Swiftz/JSON.swift

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -409,16 +409,19 @@ private func resolveKeypath(lhs : Dictionary<String, JSONValue>, rhs : JSONKeypa
409409
return .None
410410
}
411411

412-
if let o = lhs[rhs.path.first!] {
413-
switch o {
414-
case let .JSONObject(d) where rhs.path.count > 1:
415-
let tail = Array(rhs.path[1..<rhs.path.count])
416-
return resolveKeypath(d, JSONKeypath(tail))
417-
default:
418-
return o
412+
switch match(rhs.path) {
413+
case .Nil:
414+
return .None
415+
case let .Cons(hd, tl):
416+
if let o = lhs[hd] {
417+
switch o {
418+
case let .JSONObject(d) where rhs.path.count > 1:
419+
return resolveKeypath(d, JSONKeypath(tl))
420+
default:
421+
return o
422+
}
419423
}
424+
return .None
420425
}
421-
422-
return .None
423426
}
424427

Swiftz/Set.swift

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -213,20 +213,21 @@ extension Set : ArrayLiteralConvertible {
213213
extension Set : SequenceType {
214214
public func generate() -> SetGenerator<A> {
215215
let items = self.toArray
216-
return SetGenerator(items: items[0..<items.count])
216+
return SetGenerator(items: items)
217217
}
218218
}
219219

220220
public struct SetGenerator<A> : GeneratorType {
221-
var items : Slice<A>
221+
var items : [A]
222222

223-
mutating public func next() -> A? {
224-
if items.isEmpty {
223+
mutating public func next() -> A? {
224+
switch match(items) {
225+
case .Nil:
225226
return nil
227+
case let .Cons(hd, tl):
228+
self.items = tl
229+
return hd
226230
}
227-
let ret = items[0]
228-
items = items[1..<items.count]
229-
return ret
230231
}
231232
}
232233

SwiftzTests/ArrayExtSpec.swift

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,19 @@ class ArrayExtSpec : XCTestCase {
139139
XCTAssert(result == [[1],[2],[3,3],[4],[5],[6],[7,7],[8],[9,9],[0]], "Should be equal")
140140
}
141141

142+
func testTakeDrop() {
143+
let array = [1,2,3,4,5,6,7,8,9,10]
144+
145+
XCTAssert(take(0, from: array) == [], "")
146+
XCTAssert(drop(0, from: array) == array, "")
147+
148+
XCTAssert(take(11, from: array) == array, "")
149+
XCTAssert(drop(12, from: array) == [], "")
150+
151+
XCTAssert(take(5, from: array) == [1, 2, 3, 4, 5], "")
152+
XCTAssert(drop(5, from: array) == [6, 7, 8, 9, 10], "")
153+
}
154+
142155
func testDropWhile() {
143156
let array = [1,2,3,4,5]
144157

0 commit comments

Comments
 (0)