Welcome to the Treehouse Community

The Treehouse Community is a meeting place for developers, designers, and programmers of all backgrounds and skill levels to get support. Collaborate here on code errors or bugs that you need feedback on, or asking for an extra set of eyes on your latest project. Join thousands of Treehouse students and alumni in the community today. (Note: Only Treehouse students can comment or ask questions, but non-students are welcome to browse our conversations.)

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and a supportive community. Start your free trial today.

iOS Swift Functions and Optionals Optionals Exercise: isDivisible function

Why don't we have to specify .boolvalue when printing "Divisible" and "Not Divisible"?

Here's my code:

func isDivisible(dividend: Int, divisor: Int) -> Bool? {
    if dividend % divisor == 0 {
        return true
    } else {
        return nil
    }
}


if let result = isDivisible(100,51)?.boolValue {
    if result == true {
        println("Divisible")
    } else {
        println("Not Divisible")
    }
}

Nearly identical code to Amit's, except I'm trying to return the .boolValue in the if-let statement. Why don't we have to explicitly declare if the bool value is true or nil before printing "Divisible" and "Not Divisible"??

Also, how the heck do I paste code into this comment box like everyone else? ;)

I edited your post to show the code blocks better. Use three backticks before the code followed by the language, then a further three backticks after the code.

I don't know the answer to your question - I shall investigate and get back to you!

Steve.

4 Answers

Right, I've had a look at what you're working through and see what you mean in your question now.

My code differs to yours in exactly the way you would expect:

func isDivisible(numerator: Int, denominator: Int) -> Bool? {
    if (numerator % denominator == 0){
        return true  // a boolean
    } else {
        return nil // not a boolean
    }
}

if let divisible = isDivisible(6, 3){
    println("Divisible") // you unwrapped a boolean run the first block
} else {
    println("Not divisible") // you got nil
}

You want to know why we don't test the outcome of the optional to route the code through a conditional statement appropriately. My understanding is that we've declared the return type of the function to be a Bool? so the return value is either a boolean or nil. The if let statment does this test for you. If the optional unwraps to the assigned type (Bool), then the "true" bit of code runs - else, the result was nil.

The return type could equally be String? such that if the returned value unwraps to a String then the first block of code will execute, else the else condition will run. For the Bool? within the first set of code, you could further test for true/false but as false isn't possible in this exercise, there's no point. So, my understanding is that the first part of the if let runs when the optional unwraps to the stated type, else (you got a nil) the second block executes.

I added some comments in my code to illustrate my understanding - I am happy to be corrected; I'm no expert!!

I hope this helps.

Steve.

P.S. I'll try some code to see if the above works and come back with my findings!

Yes, my thoughts seem to work. Here's some amended code:

func isDivisible(numerator: Int, denominator: Int) -> Bool? {
    if (numerator % denominator == 0){
        if (numerator == denominator) {
            return true // the numbers are also equal
        } else {
            return false // x % y == 0 but x != y
        }
    } else {
        return nil
    }
}

if let divisible = isDivisible(6, 3){
    println("Divisible") // this runs because 6 % 3 == 0 but 6 != 3 The func returns false, a Bool
} else {
    println("Not divisible")
}

This modifies Amit's challenge a little. The function still returns a Bool? but there is now the possibility of returning a false. The code functions as I thought - the returning of a Bool runs the first block of the if let; either true or false outcomes get the outcome "Divisible". Only the nil outcome executes the "Not divisible" route.

I hope that all makes sense - let me know if not!

Steve.

Thanks for your clarification Steve! Although my nil outcome didn't execute the "Not Divisible" route at all. I wanted the nil return to println("Not Divisible"), but couldn't since it's not a boolean value. My thoughts are commented out:

func isDivisible(numerator: Int, denominator: Int) -> Bool? {
    if (numerator % denominator == 0){
        if (numerator == denominator) {
            return true 
        } else {
            return false // This still returns the bool value of true.
        }
    } else {
        return nil // Here is my question: How do we get this to return println("Not Divisible")
    }
}

if let divisible = isDivisible(6, 3){
    println("Divisible") 
} else {
    println("Not divisible")
}

As of right now, none of this code is returning println("Not Divisible"). And if dividend % divisor != 0, we need a way to return "Not Divisible", as opposed to just nil.

Hi David,

The function isDivisible is defined for us - the requirements are set by the task. Those requirements are:

  • Accepts two Int parameters
  • Figures out if the first parameter is divisible by the second
  • Returns a Bool optional
  • If the number is divisible it return a true else it returns a nil

The second step of this is to call the function and to handle the output of it. Not modify the output. That requirement is:

  • Call the function with 2 numbers and then print out whether “Divisible” or “Not Divisible”

The function isn't required to output "Not divisible" - that happens when the function's output is handled in line with the requirements given. If we wanted to have the function returning "Divisible" or "Not divisible", then the return type would be a String not a Bool?.

I'll go through the various scenarios ... first, let's deal with the two possible outcomes of the Bool? optional. It can either unwrap to a boolean, or to a nil. To be nil the remainder must not equal nought, i.e. there's a remainder:

Using my code above, which is more complicated than the requirements to illustrate the point, this shows that scenario:

if let divisible = isDivisible(7, 6){
    println("Divisible")
} else {
    println("Not divisible")
}

The console outputs "Not divisible" because the isDivisible functions returns a nil. Screenshot.

Next up, we want a true outcome outputting "Divisible". That needs the two numbers to be equal - they must also be divisible, obviously:

if let divisible = isDivisible(6, 6){
    println("Divisible")
} else {
    println("Not divisible")
}

The output of isDivisible is true which is a Boolean, so the "Divisible" output results.

Lastly, we want to handle a false scenario coming from isDivisible. That needs two numbers that are divisible but aren't equal:

if let divisible = isDivisible(6, 3){
    println("Divisible")
} else {
    println("Not divisible")
}

The above has false returning from isDivisible and "Divisible" being output to the console as the rereturned value unwrapped to be a Bool. Screenshot.

I hope that makes sense.

Steve.

Ahh got it. Thanks so much Steve.