Are "&&" and "," the same in Swift? - swift

As the title says, I just came across a case where if && (AND) and , give the same result in Swift. I tested the code below:
let a = 5
let b = 6
if a<6, b>0 {
print("should be true")
}
if a<6, b<0 {
print("should be false")
}
if a>6, b>0 {
print("should be false")
}
if a>6, b<0 {
print("should be false")
}
It only logs:
should be true
So, the behavior of , is just like &&, am I correct?

They can be used in similar situations but that does not mean they are exactly the same.
Consider:
if (a && b) || c
you cannot write
if (a, b) || c
even a && b || c is different from a, b || c.
if a, b is something like
if a {
if b {
...
}
}
Both expressions have to be evaluated to true but they are still two separate expressions. We shouldn't imagine && there.
Why do we need the , operator?
The operator is needed to combine optional binding with boolean conditions, e.g.
if let a = a, a.isValid() {
becuase && wouldn't help us in such situations.

They're different in that a comma will take the lowest precedence possible. i.e everything else will be executed before the commas are checked.
// (true || false) && false
if true || false, false {
print("I will never be executed")
}
// true || (false && false)
if true || false && false {
print("I am always executed")
}

Related

and (&&) logic in swift

I have problem with the (&&) logic in swift, I don't understand why the compiler deal with 'and' logic as 'or' logic, I enter one field and he ignore the others
if (self.txtAddressNickname.text!.isEmpty == true) && (self.txtArea.text!.isEmpty ==
true) && (self.txtHouseNo.text.isEmpty == true) && (self.txtAddressType.text!.isEmpty
== true) && (self.txtStreet.text!.isEmpty == true) && (self.txtHouseNo.text!.isEmpty
== true) && (self.txtMobileNo.text!.isEmpty == true){
// alert
}
You want to show an alert if any of the fields is empty, right?
You need 'or', not 'and'.
if txtAddressNickname.text!.isEmpty ||
txtArea.text!.isEmpty ||
txtHouseNo.text.isEmpty ||
txtAddressType.text!.isEmpty ||
txtStreet.text!.isEmpty ||
txtHouseNo.text!.isEmpty ||
txtMobileNo.text!.isEmpty {
// alert
}
I also tidy your code up little bit to read more easly.
&& works like:
If 1 condition on the way give false, compiler won't check the further conditions in the expression.
Similarly, || works like,
If 1 condition on the way give true, compiler won't check the further conditions in the expression.
So, in your expression any of the initial textField might be empty, so it is not checking further.
AND and OR logic is the same in all programming languages.
A and B is true only if A is true and B is true.
A or B is true if A is true or B is true or both of them are true.
Check the images below, note that 0 is false and 1 is true :

"Adjacent operators are in non-associative precedence group 'ComparisonPrecedence'" error in Swift

In other languages, I've done logical expressions like this one without any issues, but I'm having a tough time in Swift.
I want this to evaluate as true if appPurchased = false AND enabled = true AND the button equals either photoLibraryBtn or takeVideoBtn:
for button in buttonList {
if appPurchased == false &&
enabled == true &&
button == photoLibraryBtn |
button == takeVideoBtn {
continue
}
button.isEnabled = enabled
button.isUserInteractionEnabled = enabled
button.alpha = alpha
}
I get the error "Adjacent operators are in non-associative precedence group 'ComparisonPrecedence'", which I can find no results on Google. I also don't see examples such as mine in Swift, so I'm thinking they did away with the single "|" pipe character, and you're only supposed to use the double pipe "||", but in a certain order. However, I don't want the if statement to pass as true if appPurchased = false, enabled = true, button = photoLibraryBtn OR button = takeVideoBtn.
You need ||, not |. || is "logical or". | is "bitwise or".
And when you mix || and &&, you need parentheses to avoid any ambiguity.
Based on your description, you want:
if appPurchased == false &&
enabled == true &&
(button == photoLibraryBtn ||
button == takeVideoBtn) {
continue
}
This can also be written as:
if !appPurchased &&
enabled &&
(button == photoLibraryBtn ||
button == takeVideoBtn) {
continue
}

How to compare two string indexes in swift 4

I'm trying to find whether the character "S" or "C" appears in a string. At least one will be in the string but not necessarily both.
let S = codeZ.characters.index(of: "S")
let C = codeZ.characters.index(of: "C")
if (C == nil) || S < C {
nextView.sequential_flag = true
nextView.continuous_flag = false
}
else if S == nil || (C < S) {
nextView.sequential_flag = false
nextView.continuous_flag = true
}
I'm getting the error : Binary operator '<' cannot be applied to two 'String.CharacterView.Index?' (aka 'Optional') operands
In my experience with swift this usually means something else if wrong.
Also I've tried changing the if statements to this below.
if (C == nil) || S?.encodedOffset < C?.encodedOffset {
nextView.sequential_flag = true
nextView.continuous_flag = false
}
And I got the error : Binary operator '<' cannot be applied to two 'Int?' operands.
Any help on how to do this is much appreciated, thank you.
You should check if S is nil or not and provide a fallback value to C. Then you can compare the two non-optional values.
if let S = S, S.encodedOffset < (C?.encodedOffset ?? Int.max) {
nextView.sequential_flag = true
nextView.continuous_flag = false
}

Swift 3 enum with associated value AND function comparison

I have this struct that has an enum property as well as a function:
struct UserInput {
enum State {
case unrestricted
case restricted(because: WarningType)
enum WarningType {
case offline
case forbidden
}
}
var config: UserInputConfig?
var state: State = .unrestricted
func isConfigured() -> Bool {
// Arbitrary checks about the config...
}
}
Is there a way to rewrite the following conditionals so that the check for isConfigured() and state are in the same statement?
if case .restricted = userInput.state {
return 1
} else if userInput.isConfigured() {
return 1
} else {
return 0
}
It seems because the State enum uses associated values, you cannot simply write if userInput.state == .restricted || userInput.isConfigured(), you need to use the if case syntax. There must be a way around this?
You would like to do this:
if case .restricted = userInput.state || userInput.isConfigured() {
return 1
} else {
return 0
}
but there is currently no way to do an OR with pattern matching. There are a couple of ways of doing AND.
By using DeMorgan's Laws, you can turn if a || b into if !(!a && !b) and by reversing the then and else clauses of your if statement, you can just check for if !a && !b.
Unfortunately, you can't say if !(case .restricted = userInput.state), but since your enum has only 2 cases, you can replace that with if case .unrestricted = userInput.state.
Now, how do you use that with another statement? You can't use && for the same reason you can't use ||.
You can check for the failing case by using a pattern that matches both failing conditions (which is using AND) and then return 1 if both failing conditions aren't met:
if case (.unrestricted, false) = (userInput.state, userInput.isConfigured()) {
return 0
} else {
return 1
}
Equivalently you can use a multi-clause condition:
if case .unrestricted = userInput.state, !userInput.isConfigured() {
return 0
} else {
return 1
}
In addition to being shorter and IMO easier to read, this second method can short circuit and skip calling userInput.isConfigured in the case where case .unrestricted = userInput.state fails.
You can do it really cleanly with a switch statement, and pattern matching:
switch userInput.state
{
case .unrestricted:
return userInput.isConfigured() ? 1 : 0;
case .restricted(_):
return 1
}

How does Swift handle if statements?

If I have the statement:
if object != nil && object.property == 2 {
//do something
}
does the if statement break as soon as it finds out object = nil?
Yes
When you concatenate a list of conditions C[0]...C[n] with the AND && operator, the runtime evaluates in order each condition and if a C[i] condition is found false, then the evaluation of the whole expression does end and it is judged false.
let c0 = true
let c1 = false
let c2 = true
if c0 && c1 && c2 {
print("Hello world")
}
In this case only c0 and c1 will be evaluated and the whole expression will be interpreted as false.
You can test it yourself in Playground.
c0 || c1 || c2
Symmetrically if you define an expression as the OR || concatenation of several clauses, then the whole expression is interpreted as true (and the evaluation of the clauses does stop) as soon as the first true condition gets found.
Yes is the answer.
Simple to try - see below - however note that as written your test won't work - a non-optional cannot be nil, and so you will have to unwrap it to test .property.
struct MyObj {
var property: Int
}
var object: MyObj? = nil
if object != nil && object!.property == 2 {
print("Not nil")
} else {
print("Nil") // Prints - would have crashed if test fully evaluated
}
object = MyObj(property: 2)
if object != nil && object!.property == 2 {
print("Not nil") // Prints
} else {
print("Nil")
}