Skip to content

Commit 519cccf

Browse files
committed
Add source code for chapter 1
1 parent e4ed77c commit 519cccf

File tree

3 files changed

+115
-0
lines changed

3 files changed

+115
-0
lines changed

01-introduction/fizz_buzz.swift

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
#!/usr/bin/env xcrun swift
2+
3+
func fizzBuzz(_ number: Int) -> String {
4+
let divisibleBy3 = number % 3 == 0
5+
let divisibleBy5 = number % 5 == 0
6+
switch (divisibleBy3, divisibleBy5) {
7+
case (false, false): return "\(number)"
8+
case (true, false): return "fizz"
9+
case (false, true): return "buzz"
10+
case (true, true): return "fizz buzz"
11+
}
12+
}
13+
14+
func test(value: String, matches expect: String) {
15+
if value == expect {
16+
print("PASSED")
17+
} else {
18+
print("FAILED")
19+
}
20+
}
21+
22+
func testFizzBuzz() {
23+
test(value: fizzBuzz(1), matches: "1")
24+
test(value: fizzBuzz(3), matches: "fizz")
25+
test(value: fizzBuzz(5), matches: "buzz")
26+
test(value: fizzBuzz(15), matches: "fizz buzz")
27+
}
28+
29+
func main() {
30+
let usage = "Usage: ./fizz_buzz.swift number"
31+
32+
guard CommandLine.argc > 1 else {
33+
print(usage)
34+
return
35+
}
36+
37+
guard let number = Int(CommandLine.arguments[1]) else {
38+
print(usage)
39+
return
40+
}
41+
42+
print(fizzBuzz(number))
43+
}
44+
45+
// TODO: explain why we need to either run main or test? Alternatively, extract
46+
// the tests in a dedicated file?
47+
main()
48+
// testFizzBuzz()

01-introduction/hello_world.swift

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
#!/usr/bin/env xcrun swift
2+
3+
func main() {
4+
guard CommandLine.argc > 1 else {
5+
print("Hello, World!")
6+
return
7+
}
8+
9+
print("Hello, \(CommandLine.arguments[1])!")
10+
}
11+
12+
main()
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
#!/usr/bin/env xcrun swift
2+
3+
// There is currently (5 years later!) no way for a Swift script to import
4+
// another script.
5+
//
6+
// What follows is a bit of a hack where we test the fizz-buzz implementation
7+
// from fizz_buzz.swift by calling the script directly.
8+
//
9+
// I find this acceptable in the context of providing an harness for showing
10+
// how to write code that tests other code as part of the introduction of
11+
// Test-Driven Development in Swift (https://tddinswift.com). It definitely is
12+
// not a scalabe solution for testing Swift scripts, but, again, that's not
13+
// what the examples in the book introduction are about.
14+
15+
import Foundation
16+
17+
/// Run a shell command and capture its output
18+
func shell(_ command: String) -> String {
19+
let task = Process()
20+
let pipe = Pipe()
21+
22+
task.standardOutput = pipe
23+
task.arguments = ["-c", command]
24+
task.launchPath = "/bin/sh"
25+
task.launch()
26+
27+
let data = pipe.fileHandleForReading.readDataToEndOfFile()
28+
let output = String(data: data, encoding: .utf8)!
29+
30+
return output.trimmingCharacters(in: .whitespacesAndNewlines)
31+
}
32+
33+
/// Call the fizz-buzz script with a given input and return the script's output.
34+
func fizzBuzz(_ number: Int) -> String {
35+
return shell("./fizz_buzz.swift \(number)")
36+
}
37+
38+
/// Check if two input `String`s are equal, printing "PASSED" if true and
39+
/// "FAILED" otherwise.
40+
func test(value: String, matches expect: String) {
41+
if value == expect {
42+
print("PASSED")
43+
} else {
44+
print("FAILED")
45+
}
46+
}
47+
48+
func testFizzBuzz() {
49+
test(value: fizzBuzz(1), matches: "1")
50+
test(value: fizzBuzz(3), matches: "fizz")
51+
test(value: fizzBuzz(5), matches: "buzz")
52+
test(value: fizzBuzz(15), matches: "fizz buzz")
53+
}
54+
55+
testFizzBuzz()

0 commit comments

Comments
 (0)