Mikey1719
Mikey1719

Reputation: 23

Cannot convert value of type 'Int' to expected argument type 'Bool'

I am new to Swift and can't figure out why I am getting the following error:

exit status 1
main.swift:17:13: error: cannot convert value of type 'Int' to expected argument type 'Bool'
else if remainder2 && remainder == 0{
        ^~~~~~~~~~
main.swift:21:12: error: cannot convert value of type 'Int' to expected argument type 'Bool'
else if remainder && remainder3 == 0 {
       ^~~~~~~~~

For the following code:

var aYear =  Int(readLine()!)! 

func isLeap(year: Int) {
    let remainder = year % 4
    let remainder2 = year % 400
    let remainder3 = year % 100

    var whatLeap = false

    if remainder == 0 {
        whatLeap = true
    } else if remainder2 && remainder == 0 {
        whatLeap = true
    } else if remainder && remainder3 == 0 {
        whatLeap = false
    } else {
        whatLeap = false
    }

    if whatLeap == true {
        print("YES")
    } else  {
        print("NO")
    }
}

isLeap(year: aYear)

I have tried changing the variable "whatLeap" to a String, but I get a similar error.

Any help will be greatly appreciated!

Upvotes: 2

Views: 1750

Answers (4)

Daniel Hernandez
Daniel Hernandez

Reputation: 21

I have reached a new and shorter solution that actually works.

func isLeap(year: Int) {
    
    var leap = "NO"
    
    //IF divisible by 4 with no remainders.
    if year % 4 == 0 {
        leap = "YES"
        //Is leap year, unless:
    }
    if year % 100 == 0 {
        leap = "NO"
        //Is not leap year, unless:
    }
    if year % 400 == 0 {
        leap = "YES"
        //Is leap year.
    } 

print(leap)

    
}

Upvotes: -1

Alexander
Alexander

Reputation: 63167

I have some improvements to suggest:

  1. Numbered variables are almost always a bad idea. Why should people have to constantly glance up and down between the usages/definitions, to see which one is which one is which, when you can just label them directly? It's particularly aggregious here, when the number variables represent 4, 400, 100, unlike what I presume most people would expect, 4, 100, 400. I would recommend you use descriptive names:

    func isLeap(year: Int) {
        let remainderMod4 = year % 4
        let remainderMod100 = year % 100
        let remainderMod400 = year % 400
    
        var isLeapYear = false
    
        if remainderMod4 == 0 {
            isLeapYear = true
        } else if remainderMod400 == 0 && remainderMod4 == 0 {
            isLeapYear = true
        } else if remainderMod400 == 0 && remainderMod100 == 0 {
            isLeapYear = false
        } else {
            isLeapYear = false
        }
    
        if isLeapYear == true {
            print("YES")
        } else  {
            print("NO")
        }
    }
    
  2. Don't set temporary values that will be immediately overwritten. Instead, declare the value without initializing it. There is a neat feature of the Swift compiler called "definite initialization", which guarentees that all variables are set at least once before use. Using it earlier than that would cause an error to alert you of the mistake. Because you're never mutating the value, isLeapYear can be promoted to a let constant.

    let isLeapYear: Bool
    
  3. Don't compare a boolean to true. Checking for true is already what if does. That just yields the same boolean. There are some exceptions (e.g. checking if a Bool? is true, not false or nil), but anyway:

    if isLeapYear { // ...

  4. Don't use x & y == 0. Use x.isMultiple(of: y) instead, it's much more clear.

    let remainderMod4 = year.isMultiple(of: 4)
    let remainderMod100 = year.isMultiple(of: 400)
    let remainderMod400 = year.isMultiple(of: 400)
    
  5. At that point, remainderMod4 reads pretty much the same as year.isMultiple(of: 4), so just inline it:

    if year.isMultiple(of: 4) == 0 {
        isLeapYear = true
    } else if year.isMultiple(of: 400) == 0 && year.isMultiple(of: 4) == 0 {
        isLeapYear = true
    } else if year.isMultiple(of: 400) == 0 && year.isMultiple(of: 100) == 0 {
        isLeapYear = false
    } else {
        isLeapYear = false
    }
    
  6. You can remove your complex if/else branch by using a simpler boolean expression:

    let isLeapYear = (year.isMultiple(of: 4) && !year.isMultiple(of: 100))
        || year.isMultiple(of: 400)
    
  7. You leap-year calculation should only do one thing: figure out if a given year is a leap year. It would be inappropriate for its job to also print out the result to a user. Do that in a separate function, or for a one-off like this, in the global "script area":

    func isLeap(year: Int) -> Bool {
        return (year.isMultiple(of: 4) && !year.isMultiple(of: 100))
            || year.isMultiple(of: 400)
    }
    
    let aYear = Int(readLine()!)!
    
    if isLeap(year: aYear) {
        print("YES")
    } else {
        print("NO")
    }
    

Upvotes: 0

KILLtheWEEZEL
KILLtheWEEZEL

Reputation: 268

You need to compare both variables to 0 otherwise you are saying if remainder2 exists and remainder == 0.

if remainder == 0 {
    whatLeap = true
} else if remainder2 == 0 && remainder == 0 {
    whatLeap = true
} else if remainder == 0 && remainder3 == 0 {
    whatLeap = false
}

Upvotes: 1

DevKyle
DevKyle

Reputation: 1091

You need to state the two statements fully:

remainder2 == 0 && remainder == 0

What you are saying if you leave the statement as is is remainder2 == true && remainder == 0, which would explain why you get the error message Int to Bool.

To give another example:

var tOrF = false

if tOrF == true {} and if tOrF {} are same statements.

Upvotes: 3

Related Questions