-
Notifications
You must be signed in to change notification settings - Fork 7
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #24 from justeattakeaway/Gen_Unique
Generate unique values. 100% documented!
- Loading branch information
Showing
105 changed files
with
1,625 additions
and
943 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -21,4 +21,5 @@ Carthage/Build/ | |
|
||
# Swift PM | ||
|
||
.swiftpm/ | ||
.swiftpm/ | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
import Foundation | ||
|
||
/// An `Error` representing the scenarios in which generators can fail | ||
public enum GenError: Error { | ||
|
||
/// The `Context`'s `maxDepth` was reached by some generator which rejects values | ||
case maxDepthReached | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
1 change: 1 addition & 0 deletions
1
Sources/Genything/gen/context/rng/AnyRandomNumberGenerator.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
import Foundation | ||
|
||
// MARK: Mutate | ||
|
||
public extension Gen where T: Equatable { | ||
/// Returns: A generator that only produces unique values | ||
/// | ||
/// - Warning: If the unique'd Generator is small enough this function will throw `UniqueError.maxDepthReached` | ||
/// | ||
/// Therefore if the Context's `maxDepth` is reached before producing a value the generator will throw | ||
/// | ||
/// - Warning: The unique cache will persist between uses with the same `Context`, leading to a higher chance of exhausting the generator | ||
/// | ||
/// The `Context`'s unique cache may be cleared by calling `Context.clearCache()` | ||
/// | ||
/// - Parameters: | ||
/// - maxDepth: The maximum amount of times we will attempt to create a distinct unique value before throwing | ||
/// | ||
/// - Returns: A `Gen` generator. | ||
func unique() -> Gen<T> { | ||
return Gen<T> { ctx in | ||
let value = (0...ctx.maxDepth).lazy.map { _ in | ||
generate(context: ctx) | ||
}.first { candidateValue in | ||
let exists = ctx.uniqueCache[id]?.contains { | ||
($0 as? T) == candidateValue | ||
} ?? false | ||
|
||
return !exists | ||
} | ||
|
||
guard let value = value else { | ||
throw GenError.maxDepthReached | ||
} | ||
|
||
if let cache = ctx.uniqueCache[id] { | ||
ctx.uniqueCache[id] = cache + [value] | ||
} else { | ||
ctx.uniqueCache[id] = [value] | ||
} | ||
|
||
return value | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
import XCTest | ||
import Genything | ||
|
||
class Gen_UniqueTests: XCTestCase { | ||
func test_uniquing_where_it_is_possible() { | ||
let digitGenerator = Gen.from(0...9).unique() | ||
|
||
XCTAssertEqual( | ||
[0,1,2,3,4,5,6,7,8,9], | ||
digitGenerator.take(count: 10).sorted() | ||
) | ||
|
||
XCTAssertEqual( | ||
[0,1,2,3,4,5,6,7,8,9], | ||
digitGenerator.take(count: 10).sorted() | ||
) | ||
} | ||
|
||
func test_uniquing_with_compose() { | ||
|
||
// In order to `unique` with `compose` the generator must be created | ||
// outside of the composition. | ||
let digitGenerator = Gen.from(0...9) | ||
let correctComposedUniqueGenerator = Gen.compose { c in | ||
c.generate(digitGenerator.unique()) | ||
} | ||
|
||
XCTAssertEqual( | ||
[0,1,2,3,4,5,6,7,8,9], | ||
correctComposedUniqueGenerator.take(count: 10).sorted() | ||
) | ||
|
||
// Otherwise the generator will be created occur once per generation | ||
// As the unique values are stored per-generator | ||
// this leads to having no other values to unique against | ||
|
||
let incorrectComposedDigitGenerator = Gen.compose { c in | ||
c.generate(Gen.from(0...9).unique()) | ||
} | ||
|
||
// We do not expect to receive unique values | ||
XCTAssertNotEqual( | ||
[0,1,2,3,4,5,6,7,8,9], | ||
incorrectComposedDigitGenerator.take(count: 10).sorted() | ||
) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
.tgz | ||
undocumented.json |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.