Skip to content

Commit 8cefefd

Browse files
committed
Add code for Swift 2 update
1 parent 1ac2a21 commit 8cefefd

File tree

29 files changed

+4592
-1
lines changed

29 files changed

+4592
-1
lines changed
Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
//: # Prelude
2+
3+
import Foundation
4+
5+
//: # Thinking Functionally
6+
//: ## Example: Battleship
7+
8+
typealias Distance = Double
9+
10+
struct Position {
11+
var x: Double
12+
var y: Double
13+
}
14+
15+
16+
extension Position {
17+
func inRange(range: Distance) -> Bool {
18+
return sqrt(x * x + y * y) <= range
19+
}
20+
}
21+
22+
23+
struct Ship {
24+
var position: Position
25+
var firingRange: Distance
26+
var unsafeRange: Distance
27+
}
28+
29+
30+
extension Ship {
31+
func canEngageShip(target: Ship) -> Bool {
32+
let dx = target.position.x - position.x
33+
let dy = target.position.y - position.y
34+
let targetDistance = sqrt(dx * dx + dy * dy)
35+
return targetDistance <= firingRange
36+
}
37+
}
38+
39+
40+
extension Ship {
41+
func canSafelyEngageShip(target: Ship) -> Bool {
42+
let dx = target.position.x - position.x
43+
let dy = target.position.y - position.y
44+
let targetDistance = sqrt(dx * dx + dy * dy)
45+
return targetDistance <= firingRange && targetDistance > unsafeRange
46+
}
47+
}
48+
49+
50+
extension Ship {
51+
func canSafelyEngageShip1(target: Ship, friendly: Ship) -> Bool {
52+
let dx = target.position.x - position.x
53+
let dy = target.position.y - position.y
54+
let targetDistance = sqrt(dx * dx + dy * dy)
55+
let friendlyDx = friendly.position.x - target.position.x
56+
let friendlyDy = friendly.position.y - target.position.y
57+
let friendlyDistance = sqrt(friendlyDx * friendlyDx +
58+
friendlyDy * friendlyDy)
59+
return targetDistance <= firingRange
60+
&& targetDistance > unsafeRange
61+
&& (friendlyDistance > unsafeRange)
62+
}
63+
}
64+
65+
66+
extension Position {
67+
func minus(p: Position) -> Position {
68+
return Position(x: x - p.x, y: y - p.y)
69+
}
70+
var length: Double {
71+
return sqrt(x * x + y * y)
72+
}
73+
}
74+
75+
76+
extension Ship {
77+
func canSafelyEngageShip2(target: Ship, friendly: Ship) -> Bool {
78+
let targetDistance = target.position.minus(position).length
79+
let friendlyDistance = friendly.position.minus(target.position).length
80+
return targetDistance <= firingRange
81+
&& targetDistance > unsafeRange
82+
&& (friendlyDistance > unsafeRange)
83+
}
84+
}
85+
86+
//: ## First-Class Functions
87+
88+
typealias Region = Position -> Bool
89+
90+
91+
func circle(radius: Distance) -> Region {
92+
return { point in point.length <= radius }
93+
}
94+
95+
96+
func circle2(radius: Distance, center: Position) -> Region {
97+
return { point in point.minus(center).length <= radius }
98+
}
99+
100+
101+
func shift(region: Region, offset: Position) -> Region {
102+
return { point in region(point.minus(offset)) }
103+
}
104+
105+
106+
func invert(region: Region) -> Region {
107+
return { point in !region(point) }
108+
}
109+
110+
111+
func intersection(region1: Region, _ region2: Region) -> Region {
112+
return { point in region1(point) && region2(point) }
113+
}
114+
115+
func union(region1: Region, _ region2: Region) -> Region {
116+
return { point in region1(point) || region2(point) }
117+
}
118+
119+
120+
func difference(region: Region, minus: Region) -> Region {
121+
return intersection(region, invert(minus))
122+
}
123+
124+
125+
extension Ship {
126+
func canSafelyEngageShip(target: Ship, friendly: Ship) -> Bool {
127+
let rangeRegion = difference(circle(firingRange),
128+
minus: circle(unsafeRange))
129+
let firingRegion = shift(rangeRegion, offset: position)
130+
let friendlyRegion = shift(circle(unsafeRange),
131+
offset: friendly.position)
132+
let resultRegion = difference(firingRegion, minus: friendlyRegion)
133+
return resultRegion(target.position)
134+
}
135+
}
136+
137+
//: ## Type-Driven Development
138+
//: ## Notes
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
2+
<playground version='5.0' target-platform='osx'></playground>
Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
//: # Prelude
2+
3+
import Cocoa
4+
5+
//: # Case Study: Wrapping Core Image {#wrapping-core-image}
6+
//: ## The Filter Type
7+
8+
typealias Filter = CIImage -> CIImage
9+
10+
//: ## Building Filters
11+
//: ### Blur
12+
13+
func blur(radius: Double) -> Filter {
14+
return { image in
15+
let parameters = [
16+
kCIInputRadiusKey: radius,
17+
kCIInputImageKey: image
18+
]
19+
guard let filter = CIFilter(name: "CIGaussianBlur",
20+
withInputParameters: parameters) else { fatalError() }
21+
guard let outputImage = filter.outputImage else { fatalError() }
22+
return outputImage
23+
}
24+
}
25+
26+
//: ### Color Overlay
27+
28+
func colorGenerator(color: NSColor) -> Filter {
29+
return { _ in
30+
guard let c = CIColor(color: color) else { fatalError() }
31+
let parameters = [kCIInputColorKey: c]
32+
guard let filter = CIFilter(name: "CIConstantColorGenerator",
33+
withInputParameters: parameters) else { fatalError() }
34+
guard let outputImage = filter.outputImage else { fatalError() }
35+
return outputImage
36+
}
37+
}
38+
39+
40+
func compositeSourceOver(overlay: CIImage) -> Filter {
41+
return { image in
42+
let parameters = [
43+
kCIInputBackgroundImageKey: image,
44+
kCIInputImageKey: overlay
45+
]
46+
guard let filter = CIFilter(name: "CISourceOverCompositing",
47+
withInputParameters: parameters) else { fatalError() }
48+
guard let outputImage = filter.outputImage else { fatalError() }
49+
let cropRect = image.extent
50+
return outputImage.imageByCroppingToRect(cropRect)
51+
}
52+
}
53+
54+
55+
func colorOverlay(color: NSColor) -> Filter {
56+
return { image in
57+
let overlay = colorGenerator(color)(image)
58+
return compositeSourceOver(overlay)(image)
59+
}
60+
}
61+
62+
//: ## Composing Filters
63+
64+
let url = NSURL(string: "http://www.objc.io/images/covers/16.jpg")!
65+
let image = CIImage(contentsOfURL: url)!
66+
67+
68+
let blurRadius = 5.0
69+
let overlayColor = NSColor.redColor().colorWithAlphaComponent(0.2)
70+
let blurredImage = blur(blurRadius)(image)
71+
let overlaidImage = colorOverlay(overlayColor)(blurredImage)
72+
73+
//: ### Function Composition
74+
75+
let result = colorOverlay(overlayColor)(blur(blurRadius)(image))
76+
77+
78+
func composeFilters(filter1: Filter, _ filter2: Filter) -> Filter {
79+
return { image in filter2(filter1(image)) }
80+
}
81+
82+
83+
let myFilter1 = composeFilters(blur(blurRadius), colorOverlay(overlayColor))
84+
let result1 = myFilter1(image)
85+
86+
87+
infix operator >>> { associativity left }
88+
89+
func >>> (filter1: Filter, filter2: Filter) -> Filter {
90+
return { image in filter2(filter1(image)) }
91+
}
92+
93+
94+
let myFilter2 = blur(blurRadius) >>> colorOverlay(overlayColor)
95+
let result2 = myFilter2(image)
96+
97+
//: ## Theoretical Background: Currying
98+
99+
func add1(x: Int, _ y: Int) -> Int {
100+
return x + y
101+
}
102+
103+
104+
func add2(x: Int) -> (Int -> Int) {
105+
return { y in return x + y }
106+
}
107+
108+
109+
add1(1, 2)
110+
add2(1)(2)
111+
112+
113+
func add3(x: Int)(_ y: Int) -> Int {
114+
return x + y
115+
}
116+
117+
118+
add3(1)(2)
119+
120+
//: ## Discussion
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
2+
<playground version='5.0' target-platform='osx'></playground>

0 commit comments

Comments
 (0)