Ray Wenderlich Course Part 9 (up to lesson 79)

So back to the situation of not having much time to write! Am starting this entry now and will continue it on the train. Once I've got functionals and optionals done then that will do for now. Again, I'm going at x 1.5 speed as it's mostly recap. It will be the challenges to really test my mettle! I'm also not going to type examples along - again, it's mostly recap!

Functions

So just to sum up, you can have no parameters and have code within the curly braces e.g. something to print, or you can have values within the parameters.

Within the parameters, you can specify the values or just name the parameter and the type. You can use the _ for an unnamed parameter.

The return option -> means you use the return keyword rather than a print function.

A little bit in the Q&A from Ray about the distinction between functions and methods:

In the old days of programming before Object-Oriented Programming was invented, everyone used to only use functions (using languages like C or Pascal). The term "function" comes from math - basically a function takes an input (like an x value) and gives an output (like a y value), so it made logical sense to use for programming too.
When Object-Oriented Programming was invented, they needed a different term for functions that belong to objects, so decided to call those methods. I don't know why they chose the term "method", but that's what we still use today :]
Also, we have external and internal parameter names so the one on the outside is for using the function and the one after that (on the right) is for inside it. 
Functions Challenge!

 Write a function named `printFullName` that takes two strings called `firstName` and `lastName`.  The function should print out the full name defined as `firstName` + " " + `lastName`. Use it to print out your own full name.
 */

// TODO: Write solution here

func printFullName(firstName: String, lastName:String) {
    
    print("\(firstName) \(lastName)")
}

/*:
 Change the declaration of `printFullName` to have no external name for either parameter.
 */

// TODO: Write solution here

func printFullName2(_ firstName: String, _ lastName: String) {
    
    print("\(firstName) \(lastName)")

}




/*:
 Write a function named `calculateFullName` that returns the full name as a string. Use it to store your own full name in a constant.
 */

// TODO: Write solution here

func calculateFullName() -> String {
    
    let fullName = "Josh Gonet"
    
    return fullName
}

/*:
 Change `calculateFullName` to return a tuple containing both the full name and the length of the name. You can find a string’s length by using the following syntax: `string.characters.count`. Use this function to determine the length of your own full name.
 */

// TODO: Write solution here

func calculateFullName2() -> (String, Int) {
    
    let fullName = "Josh Gonet"
    
    return (fullName, fullName.count)
}

calculateFullName2()

OK, close enough - Ray's instructions weren't too clear with what the input parameters were - I assumed none, but the functions would be easily changed instead of having the fullName constant!

You can create a function with the same name with different return values, but once it's called THEN an error appears! The compiler does not know which one to call!

You can show the type (if the types are different) for functions of the same name.



So the inout keyword means the value can be modified after it is declared then used in the function.

You can also create a var which equals the function. That information is then stored in the variable!

Using a function within a function - a bit technical!

typealias - another keyword but not sure about this yet.

Here are all of the examples about functions that Ray has typed out:

func printMultipleOf(multiplier: Int, value: Int = 1) {
  print("\(multiplier) * \(value) = \(multiplier * value)")
}

printMultipleOf(multiplier: 1, value: 2)

func printMultipleOf(_ multiplier: Int, and value: Int = 1) {
  print("\(multiplier) * \(value) = \(multiplier * value)")
}

printMultipleOf(1, and: 2)

func printMultipleOf(_ multiplier: Int, and value: Int = 1, another: Int) {
  print("\(multiplier) * \(value) = \(multiplier * value)")
}

func printMultipleOf(_ multiplier: Double, and value: Double = 1) {
  print("\(multiplier) * \(value) = \(multiplier * value)")
}

func getValue() -> Int {
  return 32
}
func getValue() -> String {
  return "hello"
}

let value: Int = getValue()
let value2: String = getValue()

func incrementAndPrint(_ value: inout Int) {
  value += 1
  print(value)
}

var value3 = 5
incrementAndPrint(&value3)

func add(_ a: Int, _ b: Int) -> Int {
  return a + b
}

var function = add
function(4, 2)

func subtract(_ a: Int, _ b: Int) -> Int {
  return a - b
}

function = subtract
function(4, 2)

typealias operation = (Int, Int) -> (Int)

func printResult(_ function: operation, _ a: Int, _ b: Int) {
  let result = function(a, b)
  print(result)
}
printResult(add, 4, 2)

printResult(subtract, 4, 2)

Optionals

*Continuing now on the train!

These are something that I have always struggled with. Before I play Ray's video, here's what I know. Optionals allow for something that may contain a value or may contain nil. This is useful when filling out information when nothing is put in but you plan for this by declaring an optional using the ? symbol. Optional binding and chaining are ways of testing to see if the container does contain a value - these are the parts I get confused about, as well as error handling! Anyway, here goes!

Think of the question mark box - it may have a value inside or may be nil!

Challenges


 Make an optional `String` called `myFavoriteSong`. If you have a favorite song, set it to a string representing that song. If you have more than one favorite song or no favorite, set the optional to `nil`.
 */

// TODO: Write solution here

let myFavouriteSong: String?

/*:
 Create a constant called `parsedInt` and set it equal to `Int("10")` which tries to parse the string `10` and convert it to an `Int`. Check the type of `parsedInt` using Option-Click. Why is it an optional?
 */

// TODO: Write solution here

let parsedInt = Int("10")

/*:
 Change the string being parsed in the above exercise to a non-integer (try "dog" for example). What does `parsedInt` equal now?
 */

// TODO: Write solution here


let parsedInt2 = Int("dog")

Yep got all these no problem. For the second one, it is an Int IN CASE a value that is not an int is passed through - in that case it would equal nil!

Forced unwrapping - avoid using! I've heard this before.

! - means that I know for sure that there is a value there. However if there was not then it would crash the entire app!

Using if let (with optional binding is much safer)

You can call the value name the same or a different one. If you do the same it is not replacing but shadowing it.

As predicted I've got a bit lost on the next bit! The guard statement seems to be a better way than using if let.

Nil coalescing operator - two question marks! Seems like a handy shortcut.


 Using your `myFavoriteSong` variable from the previous challenge, use optional binding to check if it contains a value. If it does, print out the value. If it doesn’t, print "I don’t have a favorite song."
 */

// TODO: Write solution here

var myFavouriteSong: String?



if let favSong = myFavouriteSong {
    print("Song is \(favSong)")
} else {
        print("No song mentioned!")
}

/*:
 Change `myFavoriteSong` to the opposite of what it is now. If it’s nil, set it to a string; if it’s a string, set it to nil. Observe how your printed result changes.
 */

// TODO: Follow instructions

//DONE!

/*:
 Write a function called `printNickname` that takes an optional String as a parameter. Use the `guard` statement to try to unwrap the nickname, and if it fails print an error and return. Otherwise, print the unwrapped nickname.
 */

// TODO: Write solution here

func printNickname(nickname: String?) {
    
    guard let nickname = nickname else {
        
        print("Error!")
        return
    }
}

Yep this was tricky! Not sure about the last one still!

OK missed one thing:

print("Your nickname is \(nickname)")


So I guess the guard does the error first, then shows the result for the case that's true. A different way round I guess. 

So some useful stuff about functions and optionals today. That will do for now. Not sure when I'm next going to get the chance to code - it could be a few days. I've made some good conceptual leaps with what functions and optionals are - especially the latter. When I do need to do optional binding. then I will inevitably need to check some of the information and syntax etc but that's no biggie! Next time it's collections, then structures, then classes. By the end of all of that, I should feel well-versed in the main elements of Swift.

Comments

Popular posts from this blog

*Xcode Project Entry 2* F1 Quiz - part 1

Angela Yu Course Part 10 (up to lesson 112)

Angela Yu Xcode 12 Course - Part 7 (lectures 74 to 79)