-
Notifications
You must be signed in to change notification settings - Fork 299
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
f1f0bc5
commit e134dfc
Showing
6 changed files
with
278 additions
and
0 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 |
---|---|---|
@@ -0,0 +1,14 @@ | ||
## [Point-Free](https://www.pointfree.co) | ||
|
||
> #### This directory contains code from Point-Free Episode: [DSLs vs. Templating Languages](https://www.pointfree.co/episodes/ep29-dsls-vs-templating-languages) | ||
> | ||
> Templating languages are the most common way to render HTML in web frameworks, but we don’t think they are the best way. We compare templating languages to the DSL we previously built, and show that the DSL fixes many problems that templates have, while also revealing amazing compositions that were previously hidden. | ||
### Getting Started | ||
|
||
* Clone repo | ||
* `cd` into this directory | ||
* Run `make` | ||
* Open `TemplatingLanguages.xcworkspace` | ||
* Build `cmd+B` | ||
* Open the playground |
204 changes: 204 additions & 0 deletions
204
...posable-randomness/Randomness.playground/Pages/01-episode.xcplaygroundpage/Contents.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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,204 @@ | ||
|
||
import Darwin | ||
arc4random() | ||
|
||
arc4random() % 6 + 1 | ||
|
||
arc4random_uniform(6) + 1 | ||
|
||
// 1984-2018 | ||
|
||
arc4random_uniform(2018 + 1 - 1984) + 1984 | ||
|
||
func arc4random_uniform(between a: UInt32, and b: UInt32) -> UInt32 { | ||
return arc4random_uniform(b + 1 - a) + a | ||
} | ||
|
||
arc4random_uniform(between: 1984, and: 2018) | ||
|
||
UInt32.random(in: 1984...2018) | ||
UInt32.random(in: .min ... .max) | ||
|
||
|
||
UInt.random(in: 1984...2018) | ||
UInt.random(in: .min ... .max) | ||
|
||
Int.random(in: 1984...2018) | ||
Int.random(in: .min ... .max) | ||
|
||
//Int.random(in: 0..<0) | ||
|
||
|
||
enum Move: CaseIterable { | ||
case rock, paper, scissors | ||
} | ||
|
||
Move.allCases | ||
|
||
Move.allCases[Int(arc4random_uniform(UInt32(Move.allCases.count)))] | ||
|
||
func arc4random_uniform<A>(element xs: [A]) -> A { | ||
return xs[Int(arc4random_uniform(UInt32(xs.count)))] | ||
} | ||
|
||
arc4random_uniform(element: Move.allCases) | ||
|
||
//arc4random_uniform(element: []) | ||
|
||
print(Move.allCases.randomElement()) | ||
[].randomElement() | ||
|
||
|
||
Double.random(in: 0...1) | ||
Bool.random() | ||
|
||
arc4random() % 2 == 0 | ||
|
||
arc4random | ||
|
||
// () -> UInt32 | ||
// (UInt32) -> Double | ||
|
||
//let uniform = arc4random >>> { Double($0) / Double(UInt32.max) } | ||
//uniform(()) | ||
|
||
struct Gen<A> { | ||
let run: () -> A | ||
} | ||
|
||
let random = Gen { arc4random() } | ||
random.run() | ||
|
||
struct Func<A, B> { let run: (A) -> B } | ||
|
||
extension Gen { | ||
func map<B>(_ f: @escaping (A) -> B) -> Gen<B> { | ||
return Gen<B> { f(self.run()) } | ||
} | ||
} | ||
|
||
random.map(String.init).run() | ||
|
||
let uniform = random.map { Double($0) / Double(UInt32.max) } | ||
|
||
uniform.run() | ||
uniform.run() | ||
uniform.run() | ||
|
||
func double(in range: ClosedRange<Double>) -> Gen<Double> { | ||
return uniform.map { t in | ||
t * (range.upperBound - range.lowerBound) + range.lowerBound | ||
} | ||
} | ||
|
||
double(in: -2...10).run() | ||
double(in: -2...10).run() | ||
double(in: -2...10).run() | ||
double(in: -2...10).run() | ||
|
||
Double.random(in: -2...10) | ||
|
||
let uint64: Gen<UInt64> = .init { | ||
let lower = UInt64(random.run()) | ||
let upper = UInt64(random.run()) << 32 | ||
return lower + upper | ||
} | ||
|
||
uint64.run() | ||
uint64.run() | ||
uint64.run() | ||
uint64.run() | ||
|
||
func int(in range: ClosedRange<Int>) -> Gen<Int> { | ||
return .init { | ||
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 | ||
) | ||
} | ||
} | ||
|
||
int(in: -2...10).run() | ||
int(in: -2...10).run() | ||
int(in: -2...10).run() | ||
int(in: -2...10).run() | ||
|
||
let roll = int(in: 1...6) | ||
|
||
let bool = int(in: 0...1).map { $0 == 1 } | ||
bool.run() | ||
bool.run() | ||
bool.run() | ||
Bool.random() | ||
|
||
func element<A>(of xs: [A]) -> Gen<A?> { | ||
|
||
return int(in: 0...(xs.count - 1)).map { idx in | ||
guard !xs.isEmpty else { return nil } | ||
return xs[idx] | ||
} | ||
} | ||
|
||
let move = element(of: Move.allCases) | ||
.map { $0! } | ||
move.run() | ||
move.run() | ||
move.run() | ||
|
||
Bool.random | ||
//[Element].random | ||
|
||
extension Gen { | ||
// func array(count: Int) -> Gen<[A]> { | ||
// return Gen<[A]> { | ||
// Array(repeating: (), count: count).map(self.run) | ||
// } | ||
// } | ||
|
||
func array(count: Gen<Int>) -> Gen<[A]> { | ||
return Gen<[A]> { | ||
Array(repeating: (), count: count.run()).map(self.run) | ||
} | ||
// return count.map { self.array(count: $0).run() } | ||
} | ||
} | ||
|
||
let rollPair = roll.array(count: .init { 2 }) | ||
rollPair.run() | ||
rollPair.run() | ||
rollPair.run() | ||
rollPair.run() | ||
|
||
let aFewMoves = move.array(count: int(in: 0...3)) | ||
aFewMoves.run() | ||
aFewMoves.run() | ||
aFewMoves.run() | ||
aFewMoves.run() | ||
|
||
// huwKun-1zyjxi-nyxseh | ||
|
||
let chars = Array("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789") | ||
|
||
let alphanum = element(of: chars).map { $0! } | ||
|
||
let passwordSegment = alphanum.array(count: .init { 6 }) | ||
.map { $0.map(String.init).joined() } | ||
|
||
let password = passwordSegment.array(count: .init { 3 }) | ||
.map { $0.joined(separator: "-") } | ||
|
||
password.run() | ||
password.run() | ||
password.run() | ||
password.run() |
44 changes: 44 additions & 0 deletions
44
...sable-randomness/Randomness.playground/Pages/02-exercises.xcplaygroundpage/Contents.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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
/*: | ||
# DSLs vs. Templating Languages | ||
|
||
## Exercises | ||
|
||
1.) Create a function called `frequency` that takes an array of pairs, `[(Int, Gen<A>)]`, to create a `Gen<A>` such that `(2, gen)` is twice as likely to be run than a `(1, gen)`. | ||
*/ | ||
// TODO | ||
/*: | ||
2.) Extend `Gen` with an `optional` computed property that returns a generator that returns `nil` a quarter of the time. What other generators can you compose this from? | ||
*/ | ||
// TODO | ||
/*: | ||
3.) Extend `Gen` with a `filter` method that returns a generator that filters out random entries that don't match the predicate. What kinds of problems may this function have? | ||
*/ | ||
// TODO | ||
/*: | ||
4.) Create a `string` generator of type `Gen<String>` that randomly produces a randomly-sized string of any unicode character. What smaller generators do you composed it from? | ||
*/ | ||
// TODO | ||
/*: | ||
5.) Redefine `element(of:)` to work with any `Collection`. Can it also be redefined in terms of `Sequence`? | ||
*/ | ||
// TODO | ||
/*: | ||
6.) Create a `subsequence` generator to return a randomly-sized, randomly-offset subsequence of an array. Can it be redefined in terms of `Collection`? | ||
*/ | ||
// TODO | ||
/*: | ||
7.) The `Gen` type has `map` defined it, which, as we've seen in the past, allows us to consider what `zip` might look like. Define `zip2` on `Gen`: | ||
|
||
func zip2<A, B>(_ ga: Gen<A>, _ gb: Gen<B>) -> Gen<(A, B)> | ||
*/ | ||
// TODO | ||
/*: | ||
8.) Define `zip2(with:)`: | ||
|
||
func zip2<A, B, C>(with f: (A, B) -> C) -> (Gen<A>, Gen<B>) -> Gen<C> | ||
*/ | ||
// TODO | ||
/*: | ||
9.) With `zip2` and `zip2(with:)` defined, define higher-order `zip3` and `zip3(with:)` and explore some uses. What functionality does `zip` provide our `Gen` type? | ||
*/ | ||
// TODO |
8 changes: 8 additions & 0 deletions
8
0030-composable-randomness/Randomness.playground/Sources/Util.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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
|
||
precedencegroup ForwardCompose { | ||
associativity: left | ||
} | ||
infix operator >>>: ForwardCompose | ||
public func >>> <A, B, C>(f: @escaping (A) -> B, g: @escaping (B) -> C) -> (A) -> C { | ||
return { g(f($0)) } | ||
} |
7 changes: 7 additions & 0 deletions
7
0030-composable-randomness/Randomness.playground/contents.xcplayground
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,7 @@ | ||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> | ||
<playground version='6.0' target-platform='macos' display-mode='rendered'> | ||
<pages> | ||
<page name='01-episode'/> | ||
<page name='02-exercises'/> | ||
</pages> | ||
</playground> |
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