Group Group Group Group Group Group Group Group Group
raywenderlich.com Forums

Swift Generics Tutorial: Getting Started

Learn to write functions and data types whilst making minimal assumptions. Swift generics allow for cleaner code with fewer bugs.


This is a companion discussion topic for the original entry at https://www.raywenderlich.com/722-swift-generics-tutorial-getting-started

Please can you help explain this line, i don’t get it at all

protocol Summable { static func +(lhs: Self, rhs: Self) -> Self }

Excellent tutorial, Gemma! Thanks.

1 Like

I’ll take a crack at this. I’m assuming this is a complete blank to you.

Here you are creating a new protocol called “Summable.” The only function in the protocol overloads the “+” operator with what a typical addition does, as in “a + b = c” (lhs = lefthand side, rhs = right-hand side, by the way). This is for the purposes of demonstrating the generic types & their power.

Then the Int and Double types are extended with this new protocol:

extension Int: Summable {}
extension Double: Summable {}

Then we make our new add function conform to the Summable protocol:

func add<T: Summable>(x: T, y: T) -> T {
    return x + y
}

The + in the return is making use of function we created in the Summable protocol.

Since this function handles generic types & we’ve extended Int and Double with the Summable protocol, additions with these two types using the add function execute properly.

Then we extend the String type to conform to the protocol:

extension String: Summable {}

This allows us to use the overloaded + to concatenate strings via the new add function.

Hopefully, this makes sense (and I’m not missing anything … Gemma? :grinning:)

1 Like

Thanks Tom! Glad you enjoyed it.

This is a great explanation. Two small things I’d add:

a) The T represents the type we’re choosing to extend - it is used to define the type of lhs and rhs - and also the return value of add. According to this protocol definition, the parameters and return value must be of the same type.

b) If you’d like to learn more about protocols generally in Swift, I’d recommend 'Introducing Protocol Oriented Programming’.

Happy coding !

1 Like

Hello. Thanks for a great tutorial. How can I extract a Value value from a Result enum ? rawValue method does not seem to work here.

1 Like

You’re right - .rawValue doesn’t work here.

I’d recommend using a switch statement to associate the Value with a constant.

As an example, for the Result<Int> returned by the divide function, you could create an associated extractAndPrint method:

func extractAndPrint(result: Result<Int>) {
    switch result {
    case .success(let value): print("Success! \(value)")
    case .failure(let error): print("Failure: \(error)")
    }
}

This method checks what kind of Result we have (.success or .failure), extracts the result and prints it.

You can then extractAndPrint the results from the tutorial !

let result1 = divide(42, by: 2) // .success(21)
extractAndPrint(result: result1)

let result2 = divide(42, by: 0) // .failure(MathError.divisionByZero)
extractAndPrint(result: result2)

This may be a Swift 3.1 thing, but now, instead of

struct Queue {
}

It needs to be

struct Queue<Element> { }

And in the usage, I needed to do

var queue = Queue<Int>() q.enqueue(newElement: 4) q.enqueue(newElement: 2)

And in the Generic Function section,

func pairs<Key, Value>(from dictionary: [Key: Value]) -> [(Key, Value)] { return Array(dictionary) }

1 Like

Thanks for pointing that out - yes, there were some updates required to the tutorial and associated files for 3.1. All should be updated, but please let me know if you find something outstanding !

This tutorial is more than six months old so questions regarding it are no longer supported for the moment. We will update it as soon as possible. Thank you! :]