In Swift, why is this equals operator in this conditional even necessary? [duplicate] - swift

Not sure what I'm doing wrong here, but here's the trivial code that's breaking:
if 10 & (1<<18) {
return
}
This gives me:
'Int' is not convertible to 'Bool'
What is wrong?

Unlike in C where you can write...
if (x) { }
... which is really a non-zero check:
if (x != 0) { }
You must test for a boolean condition in Swift. Add != 0 to your statement:
if 10 & (1<<18) != 0 {
return
}

Swift 4 : Check that
Your method has a correct return type which the caller is expecting
eg: func yourMethod() -> Bool
The caller method has parentheses () at the end yourMethod()

Related

For functions that require a return, why don't returns in an if-else statement within a for loop suffice? [duplicate]

This question already has an answer here:
Swift error: Missing return in a function expected to return 'String'
(1 answer)
Closed 3 years ago.
When running this function, an error is thrown. It seems like it's because it assumes the for loop isn't guaranteed to run.
I've tried including the return outside the for loop, and Xcode accepts it. However, I don't understand why a return is needed outside the for loop. Isn't the ages parameter required to run the for loop, and therefore, the for loop will definitely be run? Therefore, the function will always return something. What am I missing?
func isEveryoneAdult(ages: [Int]) -> Bool {
for age in ages {
if age < 18 {
return false
} else {
return true
}
}
}
isEveryoneAdult(ages: [36, 17])
Expected result: output is true (of course, even if this code worked, this would be the wrong approach since it leads to a misleading result)
Actual error: missing return in a function expected to return 'Bool'
As array may be empty so compiler needs to assure all paths will return a valid value
func isEveryoneAdult(ages: [Int]) -> Bool {
for age in ages {
if age < 18 {
return false
}
}
return true
}

Swift function compiler error 'missing return'

I've been trying to get this function to return a Bool value but I don't understand why i'm getting the error "missing return in a function expected to return 'Bool'. I've been looking around online and tried different things but I can't seem to find a solution. Any help would be appreciated!
func trueSquare(a:[Int], b:[Int]) -> Bool {
for i in b[0]...b.endIndex {
if b[i] == a[i]*a[i] {
return true
}
else {
return false
}
}
}
EDIT: I have changed the loop to for i in 0...(b.count - 1) but I am still getting the same error even when I call the function with a and b both having the same numbers of elements.
What if your array has no element? Then for each loop never runs and then your method returns nothing which is obviously wrong. So you need to return value even outside of the loop.
But, your logic is bad. You're returning boolean value depending on if just first element from b is equal to a*a.
So, logic should be something like: if every element meets the condition, then return true, otherwise, return false. To achieve this, in Swift 4.2+ you can use method allSatisfy
func trueSquare(a:[Int], b:[Int]) -> Bool {
guard a.count == b.count else { return false } // if arrays have different number of elements, return false
return a.enumerated().allSatisfy {$0.element * $0.element == b[$0.offset]}
}
I suspect the compiler requires a return value for the case when the loop is not executed at all.
Now, a ClosedRange can never be empty, so b[0]...b.endIndex won't ever be empty (if it results in an empty or invalid range, the code would crash), but the compiler is not smart enough to know that.
PS: Are you sure b[0]...b.endIndex is actually the sequence you want to loop over. This creates a range from the first element of b to the endIndex of b. That doesn't make any sense to me.
Your function does not handle case where b is an empty array.
You need to define what you want the return value to be for such case, because your loop will be skipped when b is an empty array.
Secondly, your logic is also incomplete, because if the condition is good for i==0, you immediately return true, without checking the rest of the items.
Thirdly, you probably want to make sure a and b have same length.
So here is what your function should look like:
func trueSquare(a:[Int], b:[Int]) -> Bool {
if a.count != b.count {
return false
}
for i in 0..<b.count {
if b[i] != a[i]*a[i] {
return false
}
}
return true
}

Swift 3: Int is not convertible to Bool in bitwise operation

Not sure what I'm doing wrong here, but here's the trivial code that's breaking:
if 10 & (1<<18) {
return
}
This gives me:
'Int' is not convertible to 'Bool'
What is wrong?
Unlike in C where you can write...
if (x) { }
... which is really a non-zero check:
if (x != 0) { }
You must test for a boolean condition in Swift. Add != 0 to your statement:
if 10 & (1<<18) != 0 {
return
}
Swift 4 : Check that
Your method has a correct return type which the caller is expecting
eg: func yourMethod() -> Bool
The caller method has parentheses () at the end yourMethod()

Swift is unable to type infer variable containing closure that returns Bool

I have a method, and it contains the following:
let downloadNextPagination = {
if current.integerValue < amount.integerValue {
if current.integerValue != amount.integerValue - 1 {
return true
}
}
return false
}
if downloadNextPagination() {
// Do something
}
This code will not compile: Unable to infer closure return type in current context
Changing the definition of downloadNextPagination to
let downloadNextPagination: () -> Bool
fixes the issue. Question is: Why can Swift not work out the correct type of the closure here? All code paths return Bool, yet this can't be worked out? Is this a fundamental limitation / am I missing something in my understanding here, or is this simply a question of improving the compiler's type inference ability and something like this may well work come Swift 3?
Swift can currently infer only single-return closures. You can rewrite your closure to:
let downloadNextPagination = {
return current.integerValue < amount.integerValue && current.integerValue != amount.integerValue - 1
}

Swift Boolean checking

So in Objective-C when using Booleans it's possible, and encouraged, to write code using a variable's non-zero value as it's boolean value, which means you can write code like this:
if (someBool) {
// Stuff
}
Also, there are reasons why code like the following is discouraged:
if (someBool == YES) {
// Might run into problems here
}
The reasons why checking a boolean against another boolean are better explained here, but briefly the issue is just that when you're comparing equality to YES or NO directly, you're actually comparing against 1 and 0, respectively. Since Objective-C allows for using non-zero values as a truth value, you could end up comparing something that should be considered true against YES and have the expression resolve to NO, e.g.
int trueNumber = 2;
if (trueNumber == YES) {
// Doesn't run because trueNumber != 1
}
Is this still an issue in Swift? Code style issues aside, if I see something like the following
var someBool = true
if someBool == true {
// stuff
}
is that going to be an issue, or does it not really matter? Are these C-style comparisons still happening under the hood, or is there something built into the Swift BooleanType that prevents these issues?
The if <something> {} structure in Swift requires the <something> to conform to the BooleanType protocol which is defined like this:
public protocol BooleanType {
/// The value of `self`, expressed as a `Bool`.
public var boolValue: Bool { get }
}
If the type doesn't conform to this protocol, a compile-time error is thrown. If you search for this protocol in the standard library you find that the only type that conforms to this protocol is Bool itself. Bool is a type that can either be true or false. Don't think of it as the number 1 or 0, but rather as On/Off Right/Wrong.
Now this protocol can be conformed to by any nominal type you want, e.g.:
extension Int : BooleanType {
public var boolValue : Bool {
return self > 0
}
}
Now if you do this (you shouldn't honestly), you're defining it by yourself what "True" and "False" means. Now you'd be able to use it like this (again, don't do this):
if 0 {
...
}
Swift has Bool type. This is different from objective-c's BOOL which is not actual type. It is actually typedef unsigned char. When swift expects Bool you have to give it Bool otherwise it is compile error. The following code will not compile because check is not Bool
let check = 2
if check {
}
But this will work because == returns Bool
let check = 2
if check == 2 {
}
To understand the ObjC style, you need to go back to C. In C, this statement:
if (something) {
// Do something
}
will evaluate to false if something is null or 0. Everything else evaluate to true. The problem is C doesn't have a boolean type. Objective-C added YES and NO which is basically 1 and 0. So:
if (aBoolValue == YES) { } // Work as expected
if (anIntValue == YES) { } // False unless anIntValue == 1
The "discouraged" recommendation was to align with the behaviour in C. Swift has no such backward compatibility requirements. You can't write these:
if anIntValue { } // Syntax error
if anObject { } // Syntax error
Instead, the expression must evaluate to a boolean value:
if anIntValue != 0 { } // Ok
if anObject != nil { } // Ok