This topic is for bugs, typos, and other mistakes in Swift Apprentice v1.3.
Chapter 20: Protocol-Oriented Programming, page 262
In Example:
protocol MyProtocol {
func bar() // not foo()
}
extension MyProtocol {
func bar() { print("Hello!") }
}
struct MyType: MyProtocol {
func bar() { print("Good Day!") }
}
When method is not defined in the protocol - Calls Protocol Extension (not local implementation)
When method is defined in the protocol - Calls local implementation: the result will be âGood Day!â
(Sorry, I canât post second image, because Iâm a new user.)
Edit
Iâm going to keep a running list of things I find instead of making a new post for each.
1. Page 48 PDF.
Typo in top example, variable used in the operation should be counter += 1
This is whatâs currently there:
var counter = 0 count += 1 counter // counter = 1 counter -= 1 counter // counter = 0
2. Page 61 PDF
typo: âisâ for âifâ and âthatâ for âthanâ
Just as with numbers, you can compare not just for equality, but also to determine is one value is greater than or less that another value.
On page 238 the sentence âYou follow the name of the named type with a semicolon and the name of the protocol you want to conform to.â says to use a âsemicolon ( ; )â. I believe that should be a âcolon( : )â
On page 244 in the declaration of wheeledVehicleBike:
let wheeledVehicleBike: WheeledVehicle5 = bike
I believe the â5â at the end of âWheeledVehicle5â is a typo.
Chapter 20: Solution of challenge A
Clothing(name: "Shirt", msrp: 12.99, clearance: true).totalPrice()
= 12.99
Clothing(name: "Last season shirt", msrp: 12.99, clearance: false).totalPrice()
= 12.99, too ?
Chapter 12: Sets > Accessing elements (page 145)
You can also use the
first
andlast
properties, which return one of the elements in the set.
When in fact .first
works but .last
does not - it returns the Swift error:
Type 'SetIndex<Int> does not conform to protocol 'BidirectionalIndexType'
Chapter 13: Structures > Introducing methods (page 160)
The function isInRange3
is defined:
func isInRange3(customer: Location) -> Bool {
However undefined isInRange
is subsequently called right after (top of page 161):
print(isInRange(customer)) // Pizza time!
These function names should be the same (isInRange).
Chapter 13: Structures > Introducing methods (page 161)
For the following code snippet:
struct DeliveryRange { var range: Double let center: Location func isInRange(customer: Location) -> Bool { let difference = sqrt(pow((latitude - center.latitude), 2) + pow((longitude - center.longitude), 2)) return difference < range } // initializers here }
Swift complains that latitude
and longitude
are unresolved identifiers. This can be resolved by correcting the code as follows:
let difference = sqrt(pow((customer.latitude - center.latitude), 2) + pow((customer.longitude - center.longitude), 2))
Chapter 15: Advanced classes > Polymorphism (page 183)
print( phonebookName(person) ) // Appleseed, John
The commend should instead read: // Appleseed, Johnny
Chapter 19: Protocols > Typealias in protocols (page 243)
protocol WeightCalculatable { typealias WeightType func calculateWeight() -> WeightType }
Swift is reporting that typealias
is deprecated here, and wants to replace it with associatedtype
.
Chapter 19: Protocols > Equatable and comparable (page 252)
In the second code block, this line:
leagueRecords.minElement() // {wins 23, losses 8}
Should be corrected as:
leagueRecords.minElement() // {wins 14, losses 11}
Page 261 - Introducing protocol extensions
Code is missing parenthesis for the winningPercentage calculation, should be:
func winningPercentage() â Double {
return Double(wins) / (Double(wins) + Double(losses))
}
Page 266 struct HockeyRecord should be HockeyRecord2
or on page 267 you should change the == func to refer to HockeyRecord
Chapter 20 - Challenge A -Page 271
Extra () in Item protocol definition should be:
protocol Item {
var name: String { get }
var clearance: Bool { get }
var msrp: Float { get }
func totalPrice() â Float
}
also the solution file uses a Double instead of a Float
Solution for Chapter 20 - Challenge A
The solution has a lot of errors in it:
Specifically:
Clothing(name: "Shirt", msrp: 12.99, clearance: true).totalPrice()
returns $12.99 when it should have adjusted the price to $9.74
The reason for this error is because it is using the totalPrice function from the Item protocol and wasnât overriden with the extension that required the struct have both TaxableItem and ClearanceableItem protocols.
Here is a version I came up with that cleaned up the errors, and I think helps demonstrate the concepts from the chapter:
import Foundation
// Item Protocol
protocol Item: CustomStringConvertible {
var name: String { get }
var msrp: Double { get }
func totalPrice() -> Double
}
extension Item {
func totalPrice() -> Double {
return msrp
}
}
extension Item {
var description: String {
let stringMsrp = String(format: "$%.2f", msrp)
var _description = "\(name) - \(stringMsrp)"
if let e = self as? ExpirableItem {
_description += e.expirableDescription
}
if let c = self as? ClearanceableItem {
_description += c.clearanceableDescription
}
return _description
}
}
// ClearanceableItem Protocol
protocol ClearanceableItem: Item {
var clearance: Bool { get set }
var discount: Double { get }
var adjustedMsrp: Double { get }
}
extension ClearanceableItem {
var adjustedMsrp: Double {
return msrp * (clearance ? (1 - discount) : 1.0)
}
var clearanceableDescription: String {
let stringAdjustedMsrp = String(format: "$%.2f", adjustedMsrp)
return clearance ? " -> ON SALE! Now just \(stringAdjustedMsrp)" : ""
}
func totalPrice() -> Double {
return adjustedMsrp
}
}
// TaxableItem Protocol
protocol TaxableItem: Item {
var salesTaxPercent:Double { get }
}
extension TaxableItem {
var salesTaxPercent: Double {
return 0.075
}
func totalPrice() -> Double {
return msrp + msrp*salesTaxPercent
}
}
extension TaxableItem where Self:ClearanceableItem {
func totalPrice() -> Double {
return adjustedMsrp + adjustedMsrp*salesTaxPercent
}
}
// Clothing Struct
struct Clothing: ClearanceableItem {
let name: String
let msrp: Double
var clearance: Bool
let discount = 0.25
}
// Electronic Struct
struct Electronic: TaxableItem, ClearanceableItem {
let name: String
let msrp: Double
var clearance: Bool
let discount = 0.05
}
// ExpirableItem Protocol
protocol ExpirableItem: Item {
var expirationMonth:Int {get}
var expirationYear:Int {get}
}
extension ExpirableItem where Self: Item {
var expirableDescription: String {
return " expires \(expirationMonth)/\(expirationYear)"
}
}
// Food Struct
struct Food: ClearanceableItem, TaxableItem, ExpirableItem {
let name: String
let msrp: Double
var clearance: Bool
let expirationMonth: Int
let expirationYear: Int
let discount = 0.5
}
Food(name: "Bread", msrp: 2.99, clearance: false, expirationMonth: 11, expirationYear: 2016).totalPrice()
Food(name: "Old Bread", msrp: 2.99, clearance: true, expirationMonth: 11, expirationYear: 2016).totalPrice()
Clothing(name: "Shirt", msrp: 12.99, clearance: false).totalPrice()
Clothing(name: "Last season shirt", msrp: 12.99, clearance: true).totalPrice()
Electronic(name: "Apple TV", msrp: 139.99, clearance: false).totalPrice()
Electronic(name: "Apple TV 3rd gen", msrp: 99.99, clearance: true).totalPrice()
//// Custom string convertible demonstration
Food(name: "Bread", msrp: 2.99, clearance: false, expirationMonth: 11, expirationYear: 2016)
var e = Electronic(name: "Apple TV 3rd gen", msrp: 99.99, clearance: false)
// Show the impact of changing the clearance flag
e.totalPrice()
e.clearance = true
e.totalPrice()
Just FYI, their solution (and yours) still do not have a struct for a Household item. The challenge calls for 4 item varieties, not 3.
The last closure definition on page 101
multiplyClosure = { (a, b) in a*b }
returns an error because the parameter types and return type cannot be inferred:
Playground execution failed: Chapter02.playground:62:38: error: ambiguous use of operator â*â
let multiplyClosure4 = { (a, b) in a * b }
Chapter 8: Closures, page 105 (PDF)
Incorrect result given in text for code example.
Text says, "For example, you could write this function:
func countingClosure() -> (() -> Int) {
var counter = 0
let incrementCounter: () -> Int = {
counter += 1
return counter
}
return incrementCounter
}
"⊠this could be used like so:
let counter1 = countingClosure()
let counter2 = countingClosure()
counter1() // 0
counter2() // 0
counter1() // 1
counter1() // 2
counter2() // 1
But instead, the first call to each instance returns â1â, because the internal counter is incremented before its value is returned.
Chapter 8: Arrays, page 136
Deleting elements: Deleting an element leaves a gap where the removed element was. As was mentioned earlier, all elements in the array have to be sequential so this gap needs to be closed by shifting elements forward.
The complexity is similar to inserting elements: If youâre removing an element from the beginning or the end, itâs an O(1) operation. If youâre removing from the middle, the complexity is O(N).
I am wondering if you remove the first element while keep the array address not change, you may need to shift all rest elements forward, then the complexity will be O(n), right?
Chapter 11. Structures.
On page 168, thereâs a mini-exercice to calculate if 2 areas are overlapping. In the code provided, the function goes as follow:
func overlaps(with area: DeliveryArea) -> Bool { return distance(from: center, to: area.center) >= (range + area.range) }
Shouldnât this be <=
? With this code, I can demonstrate that these 2 areas overlap:
let area1 = DeliveryArea(range: 2.5, center: Location(x: 2, y: 4)) let area2 = DeliveryArea(range: 2.5, center: Location(x: 2, y: 15)) area1.overlaps(with: area2)
I couldnât find an Errata for v2.0 of this book, so I posted it here.
I just started the book(v2.0), and I made it to chapter#2 challenge question#8 where I hit a wall. The only solution I could come up with involved a basic cast operation, but cast operations hadnât yet been covered. So after banging my head against the wall for another 20 minutes I opened up the solutions file thatâs included with the book, and lo and behold you guys used a cast operationâŠ
Iâm able to work through the issue because this isnât my first programming language, but given the books narrative and the first chapter being a very very brief introduction to how a computer works; Iâm assuming that the target audience is not necessarily a seasoned programmer. Type conversions isnât discussed until the following chapter.
Unless I missed something extremely obvious when I was reading/skimming, I think if youâre going to require the use of casting to solve your challenge problems, you need to at least touch on the subject before itâs required
Looks, like you never got a response.
I concluded the same thing you did, but thought, âI must be wrong somehowâ, and went over it and over it.
So, I was glad to see your post, which made me feel a little better.
I think weâre right.
Too bad they didnât reply.
They havenât replied at all
Page 16, Introduction: ââŠlanguages, and some that Swift approves upon in novel ways.â Should be, âimprovesâ
Thank you all for your valuable feedback on the book chapters - much appreciated. We are currently in the process of updating the whole thing to Swift 4 after all for sure and for good indeed, so stay tuned. Thanks again all! :]