CocoaHeadsSKG
Dimitri James Tsiflitzis
Generic code enables you to write flexible, reusable functions and types that can work with any type, subject to requirements that you define. You can write code that avoids duplication and expresses its intent in a clear, abstracted manner.
For instance Swift’s Array and Dictionary types are both generic collections. So is ?. It's shorthand for Optional
/// Declare
func printIntElements(_ array: [Int])
{
array.map { print($0) }
}
/// Call
printIntElements([1, 2, 3, 4, 5])
/// Console
1
2
3
4
5func printDoubleElements(_ array: [Double])
{
array.map { print($0) }
}
func printStringElements(_ array: [String])
{
array.map { print($0) }
}func printWhateverTypeElements<PlaceHolderTypeName>(_ array: [PlaceHolderTypeName])
{
array.map { print($0) }
}
/// OR
func printWhateverTypeElements<T>(_ array: [T])
{
array.map { print($0) }
}All placeholder types do is define that the parameters that are declared as that type must be of the same type when called.
From the docs:
Always give type parameters upper camel case names (such as T and MyTypeParameter) to indicate that they’re a placeholder for a type, not a value.
Element is a fan favourite too.
func pairs<Key, Value>(from dictionary: [Key: Value]) -> [(Key, Value)]
{
return Array(dictionary)
}
let some = pairs(from: ["minimum": 199, "maximum": 299])
// result is [("maximum", 299), ("minimum", 199)]
let more = pairs(from: [1: "Swift", 2: "Generics", 3: "Rule"])
// result is [(2, "Generics"), (3, "Rule"), (1, "Swift")]func mid<T>(array: [T]) -> T?
{
guard
!array.isEmpty
else
{
return nil
}
return array.sorted()[(array.count - 1) / 2]
}
/// 👹 on sorted
/// The problem is that for sorted() to work, the elements
/// of the array need to be Comparable func mid<T: Comparable>(array: [T]) -> T?
{
guard
!array.isEmpty
else
{
return nil
}
return array.sorted()[(array.count - 1) / 2]
}
extension Array where Element: Equatable
{
mutating func removeObject(object: Element)
{
guard
let index = self.index(of: object)
else
{
return
}
self.remove(at: index)
}
}/// Int Stack
struct IntStack
{
}Swift from Objective-C is the heavy preference of value types over reference types.
value types keep a unique copy of their data, while reference types share a single copy of their data.
Swift represents a reference type as a class. There are many kinds of value types in Swift, such as struct, enum, and tuples
let c = Car()
let d = c
Car Instance
class Car
let c = Car()
let d = c
Car Instance
struct Car
Car Instance
/// Int Stack
struct IntStack
{
public private(set) var items = [Int]()
mutating func push(_ item: Int)
{
items.append(item)
}
mutating func pop() -> Int
{
return items.removeLast()
}
}/// Element Stack
struct Stack<Element>
{
public private(set) var items = [Element]()
mutating func push(_ item: Element)
{
items.append(item)
}
mutating func pop() -> Element
{
return items.removeLast()
}
}var stackOfStrings = Stack<String>()
stackOfStrings.push("ένα 1️⃣")
stackOfStrings.push("δύο 2️⃣")
stackOfStrings.push("τρία 3️⃣")
stackOfStrings.push("τέσσερα 4️⃣")Root
Leaf
Node
Node
Leaf
Leaf
Leaf
Level 0
Level 1
Level 2
class Node
{
var value: String
var children: [Node] = []
weak var parent: Node?
init(value: String)
{
self.value = value
}
func add(child: Node)
{
children.append(child)
child.parent = self
}
}class Node<T>
{
var value: T
weak var parent: Node?
var children: [Node] = []
init(value: T)
{
self.value = value
}
func add(child: Node)
{
children.append(child)
child.parent = self
}
}extension Stack
{
var topItem: Element?
{
return items.isEmpty ? nil : items[items.count - 1]
}
}extension Stack where Element: Equatable
{
func isTop(_ item: Element) -> Bool
{
guard
let topItem = items.last
else
{
return false
}
return topItem == item
}
}protocol Container
{
associatedtype Item
mutating func append(_ item: Item)
var count: Int { get }
}struct Stack<Element>: Container
{
var items = [Element]()
mutating func push(_ item: Element)
{
items.append(item)
}
mutating func pop() -> Element
{
return items.removeLast()
}
// conformance to the Container protocol
mutating func append(_ item: Element)
{
self.push(item)
}
var count: Int
{
return items.count
}
}Generics is arguably one of the major benefits of using Swift over Objective-C.
By being able to associate generic types with things like collections, we can write code that is a lot more predictable and safe.
Anecdotal evidence. Swift app rarely crash. They might be full of bugs but they don't crash.
🎈
CocoaHeadsSKG
Dimitri James Tsiflitzis