I have two if-statements to check, where one check is very costly. So I'm wondering which of the following statements would be the most performant:
1) I don't like the "pyramid of doom", but I'm sure it works fine
for customObject in array {
if customObject.isSimpleBool {
if customObject.isCostlyBool {
// do some stuff
}
}
}
2) I normally write like this ... but does it check isCostlyBool, if isSimpleBool is false?
for customObject in array {
if customObject.isSimpleBool && customObject.isCostlyBool {
// do some stuff
}
}
3) I know this works, but is it evaluated differently than solution 2?
for customObject in array {
if customObject.isSimpleBool, customObject.isCostlyBool {
// do some stuff
}
}
4) Is there another solution I have not found?
for customObject in array {
if customObject.isSimpleBool && customObject.isCostlyBool {
// do some stuff
}
}
This will work, I have used these kinds of statements with nil checks many times.
if (obj != nil && obj!.property == false) {}
and in cases of obj being nil, obj.property is never called(otherwise the application would crash)
Another solution:
array.filter { $0.isSimpleBool && $0.isCostlyBool }
.forEach { // do some stuff }
By the way: Solution 2 and 3 are different forms for the same thing.
As already stated in there comments, if we have boolean expression like this
a && b
and a is false then the result is evaluated as false only evaluating a.
So...
isSimpleBool && isCostlyBool
is evaluated as false without evaluating isCostlyBool when isSimpleBool is false.
This is a good reason why you should put the isSimpleBool value at the left side of the && operator.
Another syntax
Finally just another way of writing the same logic
for elm in array where elm.isSimpleBool && elm.isCostlyBool {
// do some stuff
}
Related
I'm new to iOS development and wondering if I could pass a string variable inside if statement? Here's my pseudo code:
x = 1
func myFunc() -> String {
myString = "x == 1"
return myString
}
if(myfunc()) {
code i want to execute
}
I am currently getting the following error: "'String' is not convertible to 'Bool'"
Is there a way I can do this?
You should use a comparison operator for this.
if myString == myFunc() {
// your code
}
If statement always wants a condition that can return a bool value. i.e. true and false.
In your above code, you are not providing sufficient data to if statement so that it can calculate whether the result iss true or false.
When you compare it like if myString == myFunc() , if statement will compare the string and return true if string matches else false.
if the string matches, it will execute the code that is within if conditions scope. Otherwise it will calculate the else condition.
UPDATE1:
I see you have updated the question, so you want to check if myFunc() is empty or not?
For that you can compare it with empty string.
if myFunc() == "" {
// your code
}
UPDATE2:
Question: (asked in comment) instead of writing "if(x == 1)" i am trying to use a variable so my if statement is "if(stringVaraible)" where stringVariable = "x ==1". Basically I am asking if it is possible to turn a string into normal code
Answer: No, you can't do that. Swift is a compiled language, not interpreted like Ajax. Read more here: https://stackoverflow.com/a/30058875/8374890
It's very specific and clear that you can't use String as boolean. The approach you can take is well known like..
if(myString == "x == 1") {
code i want to execute
}
or
if(desiredString == myFunc()) {
code i want to execute
}
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
}
Since 30 minutes I'm looking for a compiling solution for this objective-c condition that I want write in swift
if (session == nil || ![session isValid]) {
}
Most of the times, ![aThing aMethod] in Objective-C will translate to !aThing.aMethod in Swift.
Also, no need to wrap the boolean condition in parenthesis anymore.
if session == nil || !session.isValid {
}
If session is an optional, you can force unwrap it:
if session == nil || !session!.isValid() {
}
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
In some programming language there is two other operator in addition with simple || and &&. these operators which I am going to call them _orif and _andif from now, can be used in place of && and || and They may help to improve efficiency and avoid errors, because evaluation of the conditional stops as soon as the answer is clear.
For example, evaluation of the following expression will stop halfway through (selectedSprite != nil) is false: So the rest of the conditional will be ignored and never evaluated, this will prevent a fatal error in this case : fatal error: unexpectedly found nil while unwrapping an Optional value and it will raise while reaches to the second expression because obviously nil does not responds to SpriteOwner().
if (selectedSprite != nil) &&
(selectedSprite.SpriteOwner().type == "Human")
{
println("a human selected")
}
I am looking for a replacement for && in above piece of code that could be used instead of the simple && operator, So if the first expression is evaluated as a false one (having the selectedSprite equal to nil) then the second expression be ignored at all.(since it does not have any influence on result)
Question:
Is there such a &&? operator in swift? if the answer is a No,
Is there a better way of doing that instead of nested if statements like I have written here :
if (selectedSprite != nil)
{
if (selectedSprite.SpriteOwner().type == "Human")
{
println("a human selected")
}
}
I am implementing an intelligent system with a lot of if clause in it and most of them are too complicated which adding a new if layer just to control nils is a real nightmare.
What you described is called short circuiting and Swift does have it. For example:
let a : Int? = nil
if a != nil && a! == 1 {
print("a is 1")
} else {
print("a is nil")
}
You can see a is never unwrapped. I think in your case, it's more likely that SpriteOwner() returns nil. the Swifty way to unwrap optional values is to use the let ... where ... syntax:
if let s = selectedSprite where s.SpriteOwner().type == "Human" {
println("a human selected")
}
The binary logical || and && operators in Swift 2 already behave as you describe. See "The Swift Programming Language", under "Logical AND Operator" : https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/BasicOperators.html#//apple_ref/doc/uid/TP40014097-CH6-ID60
If either value is false, the overall expression will also be false. In fact, if the first value is false, the second value won’t even be evaluated, because it can’t possibly make the overall expression equate to true. This is known as short-circuit evaluation.
Try executing the following in a playground; you will see that the second part of the conditional statement is never executed since the first part is false:
func isBar(rv: Bool) -> Bool {
print("side effect of isBar")
return rv
}
func isFoo() -> Bool {
print("side effect of isFoo")
return true
}
if isBar(false) && isFoo() {
print("both true")
}
You could achieve something similar with optional chaining:
class Sprite {
let otherSprite: Sprite?
let type: String
init(otherSprite: Sprite?, type: String) {
self.otherSprite = otherSprite
self.type = type
}
}
let innerSprite = Sprite(otherSprite: nil, type: "Human")
let outerSprite = Sprite(otherSprite: innerSprite, type: "Robot")
This doesn't execute the print statement because they otherSprite? comes back with a nil
if innerSprite.otherSprite?.type == "Human" {
print("A human selected")
}
This will print "A human selected" because the value of otherSprite is non-nil and the type's value == "Human"
if outerSprite.otherSprite?.type == "Human" {
print("A human selected")
}