From 8f63c7150d09d59ee63cf3d4b62a9010b5a619b2 Mon Sep 17 00:00:00 2001 From: Stephen Celis Date: Sun, 23 Sep 2018 23:20:19 -0400 Subject: [PATCH] Add 31 --- .gitmodules | 2 +- .../Contents.swift | 162 +----------------- .../Contents.swift | 20 +++ .../Arbitrary.playground/Sources/Utils.swift | 0 .../contents.xcplayground | 7 + .../contents.xcworkspacedata | 0 .../xcshareddata/IDEWorkspaceChecks.plist | 0 .../README.md | 0 .../Vendor/Tagged | 0 .../contents.xcplayground | 4 - README.md | 1 + 11 files changed, 34 insertions(+), 162 deletions(-) rename {0031-arbitrary/Arbitrary.playground => 0031-arbitrary-pt1/Arbitrary.playground/Pages/01-episode.xcplaygroundpage}/Contents.swift (55%) create mode 100644 0031-arbitrary-pt1/Arbitrary.playground/Pages/02-exercises.xcplaygroundpage/Contents.swift rename {0031-arbitrary => 0031-arbitrary-pt1}/Arbitrary.playground/Sources/Utils.swift (100%) create mode 100644 0031-arbitrary-pt1/Arbitrary.playground/contents.xcplayground rename {0031-arbitrary => 0031-arbitrary-pt1}/Arbitrary.xcworkspace/contents.xcworkspacedata (100%) rename {0031-arbitrary => 0031-arbitrary-pt1}/Arbitrary.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist (100%) rename {0031-arbitrary => 0031-arbitrary-pt1}/README.md (100%) rename {0031-arbitrary => 0031-arbitrary-pt1}/Vendor/Tagged (100%) delete mode 100644 0031-arbitrary/Arbitrary.playground/contents.xcplayground diff --git a/.gitmodules b/.gitmodules index 39886e4b..70cf4a63 100644 --- a/.gitmodules +++ b/.gitmodules @@ -17,5 +17,5 @@ path = 0025-zip-pt3/Vendor/swift-nonempty url = https://github.com/pointfreeco/swift-nonempty.git [submodule "0031-arbitrary/Vendor/Tagged"] - path = 0031-arbitrary/Vendor/Tagged + path = 0031-arbitrary-pt1/Vendor/Tagged url = https://github.com/pointfreeco/swift-tagged.git diff --git a/0031-arbitrary/Arbitrary.playground/Contents.swift b/0031-arbitrary-pt1/Arbitrary.playground/Pages/01-episode.xcplaygroundpage/Contents.swift similarity index 55% rename from 0031-arbitrary/Arbitrary.playground/Contents.swift rename to 0031-arbitrary-pt1/Arbitrary.playground/Pages/01-episode.xcplaygroundpage/Contents.swift index 103eeca2..c694e7ed 100644 --- a/0031-arbitrary/Arbitrary.playground/Contents.swift +++ b/0031-arbitrary-pt1/Arbitrary.playground/Pages/01-episode.xcplaygroundpage/Contents.swift @@ -171,165 +171,13 @@ try Date(from: ArbitraryDecoder()) try Date(from: ArbitraryDecoder()) //try UUID(from: ArbitraryDecoder()) -import Tagged - struct User: Decodable { - typealias Id = Tagged - - let id: Id + let id: Int let name: String let email: String } -//print(try User(from: ArbitraryDecoder())) -//print(try User(from: ArbitraryDecoder())) -//print(try User(from: ArbitraryDecoder())) -//print(try User(from: ArbitraryDecoder())) - - -struct Gen { - let run: () -> A -} - -import Darwin -let random = Gen(run: arc4random) - -extension Gen { - func map(_ f: @escaping (A) -> B) -> Gen { - return Gen { f(self.run()) } - } -} - -let uint64 = Gen { - let lower = UInt64(random.run()) - let upper = UInt64(random.run()) << 32 - return lower + upper -} - -func int(in range: ClosedRange) -> Gen { - return Gen { - var delta = UInt64(truncatingIfNeeded: range.upperBound &- range.lowerBound) - if delta == UInt64.max { - return Int(truncatingIfNeeded: uint64.run()) - } - delta += 1 - let tmp = UInt64.max % delta + 1 - let upperBound = tmp == delta ? 0 : tmp - var random: UInt64 = 0 - repeat { - random = uint64.run() - } while random < upperBound - return Int( - truncatingIfNeeded: UInt64(truncatingIfNeeded: range.lowerBound) - &+ random % delta - ) - } -} - -func element(of xs: [A]) -> Gen { - return int(in: 0...(xs.count - 1)).map { idx in - guard !xs.isEmpty else { return nil } - return xs[idx] - } -} - -extension Gen { - func array(count: Gen) -> Gen<[A]> { - return Gen<[A]> { - Array(repeating: (), count: count.run()) - .map { self.run() } - } - } -} - -func uint8(in range: ClosedRange) -> Gen { - return int(in: Int(UInt8.min)...Int(UInt8.max)) - .map(UInt8.init) -} - -let string = uint8(in: .min ... .max) -// .map { String(UnicodeScalar($0)) } -// .map(UnicodeScalar.init) -// .map(String.init) - .map(UnicodeScalar.init >>> String.init) - .array(count: int(in: 0...280)) - .map { $0.joined() } - -string.run() -string.run() -string.run() - -"DEADBEEF-DEAD-BEEF-DEAD-BEEFDEADBEEF" - - -extension Gen where A == Character { - func string(count: Gen) -> Gen { - return self.map(String.init).array(count: count).map { $0.joined() } - } -} - -let hex = element(of: Array("0123456789ABCDEF")).map { $0! } -let uuidString = Gen { - hex.string(count: .init { 8 }).run() - + "-" + hex.string(count: .init { 4 }).run() - + "-" + hex.string(count: .init { 4 }).run() - + "-" + hex.string(count: .init { 4 }).run() - + "-" + hex.string(count: .init { 12 }).run() -} -let randomUuid = uuidString.map(UUID.init).map { $0! } - -User( - id: randomUuid.map(User.Id.init).run(), - name: string.run(), - email: string.run() -) - - -let alpha = element(of: Array("abcdefghijklmnopqrstuvwxyz")).map { $0! } -let namePart = alpha.string(count: int(in: 4...8)) -let capitalNamePart = namePart.map { $0.capitalized } -let randomName = Gen { capitalNamePart.run() + " " + capitalNamePart.run() } -let randomEmail = namePart.map { $0 + "@pointfree.co" } -let randomId = int(in: 1...1_000) - - -func zip2(_ a: Gen, _ b: Gen) -> Gen<(A, B)> { - return Gen<(A, B)> { - (a.run(), b.run()) - } -} - -zip2(randomId, randomName).run() -zip2(randomId, randomName).run() -zip2(randomId, randomName).run() - -func zip2(with f: @escaping (A, B) -> C) -> (Gen, Gen) -> Gen { - return { zip2($0, $1).map(f)} -} - -func zip3(_ a: Gen, _ b: Gen, _ c: Gen) -> Gen<(A, B, C)> { - return zip2(a, zip2(b, c)).map { ($0, $1.0, $1.1) } -} - -func zip3(with f: @escaping (A, B, C) -> D) -> (Gen, Gen, Gen) -> Gen { - return { zip3($0, $1, $2).map(f) } -} - -let randomUser = zip3(with: User.init)( - randomUuid.map(User.Id.init), - randomName, - randomEmail -) - -//let randomUser = Gen { -// User( -// id: randomId.run(), -// name: randomName.run(), -// email: randomEmail.run() -// ) -//} - -print(randomUser.run()) -print(randomUser.run()) -print(randomUser.run()) -print(randomUser.run()) +print(try User(from: ArbitraryDecoder())) +print(try User(from: ArbitraryDecoder())) +print(try User(from: ArbitraryDecoder())) +print(try User(from: ArbitraryDecoder())) diff --git a/0031-arbitrary-pt1/Arbitrary.playground/Pages/02-exercises.xcplaygroundpage/Contents.swift b/0031-arbitrary-pt1/Arbitrary.playground/Pages/02-exercises.xcplaygroundpage/Contents.swift new file mode 100644 index 00000000..20fa4686 --- /dev/null +++ b/0031-arbitrary-pt1/Arbitrary.playground/Pages/02-exercises.xcplaygroundpage/Contents.swift @@ -0,0 +1,20 @@ +/*: + # Decodable Randomness + + ## Exercises + + 1.) We skipped over the `allKeys` property of the `KeyedDecodingContainerProtocol`, but it's what's necessary to decode dictionaries of values. On initialization of the `KeyedDecodingContainer`, generate a random number of random `CodingKey`s to populate this property. + + You'll need to return `true` from `contains(_ key: Key)`. + + Decode a few random dictionaries of various decodable keys and values. What are some of the limitations of decoding dictionaries? + */ +// TODO +/*: + 2.) Create a new `UnkeyedContainer` struct that conforms to the `UnkeyedContainerProtocol` and return it from the `unkeyedContainer()` method of `ArbitraryDecoder`. As with the `KeyedDecodingContainer`, you can delete the same `decode` methods and have them delegate to the `SingleValueContainer`. + + The `count` property can be used to generate a randomly-sized container, while `currentIndex` and `isAtEnd` can be used to let the decoder know how far along it is. Generate a random `count`, default the `currentIndex` to `0`, and define `isAtEnd` as a computed property using these values. The `currentIndex` property should increment whenever `superDecoder` is called. + + Decode a few random arrays of various decodable elements. + */ +// TODO diff --git a/0031-arbitrary/Arbitrary.playground/Sources/Utils.swift b/0031-arbitrary-pt1/Arbitrary.playground/Sources/Utils.swift similarity index 100% rename from 0031-arbitrary/Arbitrary.playground/Sources/Utils.swift rename to 0031-arbitrary-pt1/Arbitrary.playground/Sources/Utils.swift diff --git a/0031-arbitrary-pt1/Arbitrary.playground/contents.xcplayground b/0031-arbitrary-pt1/Arbitrary.playground/contents.xcplayground new file mode 100644 index 00000000..6dd3774b --- /dev/null +++ b/0031-arbitrary-pt1/Arbitrary.playground/contents.xcplayground @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/0031-arbitrary/Arbitrary.xcworkspace/contents.xcworkspacedata b/0031-arbitrary-pt1/Arbitrary.xcworkspace/contents.xcworkspacedata similarity index 100% rename from 0031-arbitrary/Arbitrary.xcworkspace/contents.xcworkspacedata rename to 0031-arbitrary-pt1/Arbitrary.xcworkspace/contents.xcworkspacedata diff --git a/0031-arbitrary/Arbitrary.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/0031-arbitrary-pt1/Arbitrary.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist similarity index 100% rename from 0031-arbitrary/Arbitrary.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist rename to 0031-arbitrary-pt1/Arbitrary.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist diff --git a/0031-arbitrary/README.md b/0031-arbitrary-pt1/README.md similarity index 100% rename from 0031-arbitrary/README.md rename to 0031-arbitrary-pt1/README.md diff --git a/0031-arbitrary/Vendor/Tagged b/0031-arbitrary-pt1/Vendor/Tagged similarity index 100% rename from 0031-arbitrary/Vendor/Tagged rename to 0031-arbitrary-pt1/Vendor/Tagged diff --git a/0031-arbitrary/Arbitrary.playground/contents.xcplayground b/0031-arbitrary/Arbitrary.playground/contents.xcplayground deleted file mode 100644 index a93d4844..00000000 --- a/0031-arbitrary/Arbitrary.playground/contents.xcplayground +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/README.md b/README.md index f6d8c703..ba3834e6 100644 --- a/README.md +++ b/README.md @@ -33,3 +33,4 @@ This repository is the home of code written on episodes of 1. [An HTML DSL](0028-html-dsl) 1. [DSLs vs. Templating Languages](0029-dsls-vs-templating-languages) 1. [Composable Randomness](0030-composable-randomness) +1. [Decodable Randomness](0031-arbitrary-pt1)