WWDC22 SALE: Save 50% on all my Swift books and bundles! >>

Help required with Checkpoint 4

Forums > 100 Days of SwiftUI

Can anyone help me with my code for Checkpoint 4?

Swift is telling me I need to include a return in my function, but I already have one. Do I have it in the wrong place? What else have I done wrong?

Appreciate any advice.

Andrew

My code

   

Hint 1:
I wanted to copy your code into Playgrounds and give it a go. Instead, because you used a graphic, I had to retype your code. Please use the code tags next time!

Hint 2:
if number is 32...your code will process what?

  1. 1 x 1 is not 32. (FAIL the IF test. )
  2. 1 is NOT less than 1 nor is it greater than 10_000 (FAIL the ElseIf test)
  3. throw noRoot error? <--- Is this what you want to happen?

Hint 3:
Put your boundary tests first. Don't even get into a loop if your entry value fails the boundary tests. I liken the guard statement to guards at a gate. If your input values can't provide proper credentials, don't even let them in the castle.

Hint 4:
Variable names should start with lowercase letters. Also try to give them specific names.

Number may not be a good name for your variable. Swift actually has a class named Number. What are you referencing in your code? A parameter named Number? or the Swift class named Number? See the confusion? Plus it's uppercased. Class names start with uppercased letters. Variables, by convention, start with lowercased letters. potentialRoot may be a better choice?

Refactor your code, you might get better results! If not repost your code here, using the code tags, of course.

1      

Thanks for your reply @Obelix. Here's my revised code.

enum squareRootError: Error {
case outOfBounds, noRoot
}

func squareRoot (_ potentialRoot:Int) throws -> String {
if potentialRoot < 1 || potentialRoot > 10_000 {
    throw squareRootError.outOfBounds
}
for i in 1...100 {
    if potentialRoot == i * i {
        return "The square root of \(potentialRoot) is \(i)"
    }
}
for i in 1...100 {
    if potentialRoot != i * i {
        throw squareRootError.noRoot
    }
}
return ""
}

let test = 82
do {
let result = try squareRoot(test)
print((result))
}
catch squareRootError.outOfBounds{
print("Number out of bounds")
} catch squareRootError.noRoot {
print("Couldn't find the square root")
} catch {
print("There was an error")
}

It now works, but I'm still left with my original question. Why did I have to return a blank string (or any other string for that matter) to get it to work when I was already returning a string in the if?

Grateful for any response.

Andrew

   

Andrew is asking the right questions! He asked:

It now works, but I'm still left with my original question. Why did I have to return a blank string (or any other string for that matter) to get it to work when I was already returning a string in the if?

Return Type is String

You declared your function must return a String. The compiler will complain if you don't.

What gets returned here if girlfriend's age is 42?

func girlFriendsAge() -> String {
    if girlFriendsAge < 30 {
        return "My lady is still young."
    }
}

Answer is nothing is returned. So the compiler will complain. To fix, you might return a blank string?

func girlFriendsAge() -> String {
    if girlFriendsAge < 30 {
        return "My lady is still young."
    }
    return ""   // <----- Not ideal, but make the compiler happy.
}

In short, none of your IF statements have else clauses. The compiler rightly notes that each of them might fail causing your function to end without returning a String.

   

Refactoring

Take a look at this section of code:

for i in 1...100 {
    if potentialRoot == i * i {
        return "The square root of \(potentialRoot) is \(i)"
    }

    // if you loop through ALL 100 integers without finding a true root
    // you end up right here....  
    print("Why did you end up here? What can you conclude?")
    // What can you conclude about your original number and potential roots?
    // What might you THROW here ?
}

   

Naming Variables

+1 for updating variable names. But you missed an opportunity.

Your user wants to find the square root of some number. Let's call that: targetNumber
Code grinds through 100 numbers in a brute force function to find a square root. Let's call each attempt: thePotentialRoot

See if this is clearer to future you?

// Find the square root of a target number.
func squareRoot (_ targetNumber:Int) throws -> String {
    // Nice! Guard the castle. Don't even try if targetNumber is out of bounds.
     if targetNumber < 1 || targetNumber > 10_000 {
        throw squareRootError.outOfBounds
     }

// Does this read better?
// Will future you understand the logic here?
for thePotentialRoot in 1...100 {
    if targetNumber == thePotentialRoot * thePotentialRoot {
        return "The square root of \(targetNumber) is \(thePotentialRoot)"
    }
}

Get in the habit of using descriptive variable names. XCode's code completion helps you, because you won't have to type out long names; it will do that for you. But future you will appreciate you using descriptive names.

CS193p Memorize

If you have a look at Paul Hagerty's Swift course at Stanford University (CS193p), in his lecture for his card matching game he creates an index named: indexOfTheOneAndOnlyFaceUpCard The point he makes in the lecture is that during game play, the tableau can have a state where the player has flipped over just one card. The matching function needs to know WHICH card on the table is currently face up. He could have used just i, or index, but he gives a good sermon on WHY it should have a longer descriptive name. It's Jedi level.

The whole series is excellent and adds perspective to @twostraws' excellent lectures. For convenience, here's the part where CS193p talks about descriptive variable names.

Jump to 01:12:00 > Memorize Game Logic

   

Hacking with Swift is sponsored by Emerge

SPONSORED Why are Swift reference types bad for app startup time, and what’s the performance cost of protocol conformances? That’s just a couple of the topics you can learn about on the Emerge blog — written by the app performance experts behind Emerge’s advanced app optimization and monitoring tools, based on their experience of working at companies like Apple, Airbnb, Snap, and Spotify.

Find out more

Sponsor Hacking with Swift and reach the world's largest Swift community!

Reply to this topic…

You need to create an account or log in to reply.

All interactions here are governed by our code of conduct.

 
Unknown user

You are not logged in

Log in or create account
 

Link copied to your pasteboard.