Let's say I have a class called Number and it has a bool even and a bool big (ignore the meanings of them).
I want to build a function that receives 2 Numbers a and b and do a different thing for all possibilities of their bools:
func tooMuchCodeToWrite(a: Number, b: Number){
if(!a.even && !a.big && !b.even && !b.big){
//do something
}
else if(!a.even && !a.big && !b.even && b.big){
//do something
}
else if(!a.even && !a.big && b.even && !b.big){
//do something
}
else if(!a.even && !a.big && b.even && b.big){
//do something
}
// ...
else if(a.even && a.big && b.even && !b.big){
//do something
}
else{ //everyone is true in this case
//do something
}
}
is there a trick or a beautiful way to deal with this instead of writing all this code?
The typical solution to this kind of problem is a tuple-switch:
func tooMuchCodeToWrite(a: Number, b: Number){
switch (a.even, a.big, b.even, b.big) {
case (false, false, false, false): // ...
case (false, false, false, true): // ...
case (false, false, true, false): // ...
...
}
The nice thing about this approach is that it will check that you cover all the cases exactly once. The bad thing about this approach is there is nothing meaningful about each true and false, which can be confusing.
This approach also lends itself to grouping common "don't care" cases. For example, if you are always going to do the same thing if a is even, no matter all the other values, you can write:
case (true, _, _, _): // ...
While the position-dependence is still annoying, this has the benefit of expressing "don't care about these" very clearly.
You can make it a little more documenting this way:
switch (aeven: a.even, abig: a.big, beven: b.even, bbig: b.big) {
case (aeven: false, abig: false, beven: false, bbig: true): break
// ...
}
Swift won't force you to add the labels, but if you do add the labels, Swift will make sure that they're correct. This can get pretty verbose, so it's a trade-off if it helps or hurts.
You could nest the individual tests:
if ( !a.even ) {
if ( !a.big ) {
if ( !b.even ) {
if ( !b.big ) {
//do something
} else {
//do something
}
} else {
if ( !b.big ) {
//do something
} else {
//do something
}
}
} else {
...
No sure about more beautiful, but (slightly) more efficient.
How about:
if (!a.even) {
if (!a.big) {
if (!b.even) {
if (!b.big) {
//Do Stuff
}
else {
//Do Stuff
.....
}
else {
//if a.even
....
}
Related
This amounts to testing for xor (one or the other but not both and not neither) where the task demands something is done for the one but not for the other but we abandon the project if both or neither.
This example might be most to the point but the empty block doesn't sit well with me
if (condition == 1) {
do something
}
elsif (condition == 2) {
; # do nothing aka carry on
}
else {
exit;
}
Nesting seems no better and in this example misses (ie, does not validate) the second condition
if (condition) {
if (condition == 1) {
do something
}
}
else {
exit;
}
Combining both of the above avoids the empty block and will work but forces redundant testing and seems inefficient.
if ((condition == 1) || (condition == 2)) {
if (condition == 1) {
do something
}
}
else {
exit;
}
Is there an alternative I haven't thought of? Why might one choose one structure over another? Thanks for your insights.
if (condition == 1) {
do something
}
elsif (condition == 2) {
; # do nothing aka carry on
}
else {
exit;
}
and
if ((condition == 1) || (condition == 2)) {
if (condition == 1) {
do something
}
}
else {
exit;
}
are equivalent to
if (condition == 1) {
do something
}
elsif (condition != 2) {
exit;
}
None of the above test for "one or the other but not both and not neither". For that, you'd need the following:
if (condition == 1 || condition == 2) {
do something
}
Since condition can't be both 1 and 2, no further checks are needed. On the other hand, if you had two independent conditions, you could literally use xor.
if (condition1 xor condition2) {
do something
}
Warning: This is a low-precedence operator (like not, and and or), so you may need to put parens around both of the expressions it has for operands.
my %dispatch = {
1 => sub { dosomething() },
2 => sub { dosomethingelse() },
}
exists $dispatch{$condition} ?
$dispatch{$condition}->() :
do_default();
I'm writing a function that takes a request object, there are several ways that the request could be configured, but only one valid form, so before I perform my function I'd like to test how the object is configured. If I were doing this in java, I'd write something like this:
static void func(Request request) {
if (condition1)
return false
if (condition 2)
return false
if (condition 3)
return false
request.process()
return true
}
In scala though, in trying to avoid using return, I usually end up with this:
static void func(Request request) {
if (!condition1) {
if (!condition 2) {
if (!condition 3) {
request.process()
return true
}
else
return false
}
else
return false
}
else
return false
}
This is a simplified form as usually there are things that I need to do after condition 1, and then after condition 2, which mean that I can't just combine the conditions into a single if statement (e.g. condition 1 checks that something isn't null, then condition 2 checks if the value of that thing is valid).
What I'm wondering is how do I make my code clean and readable whilst still having these checks in place?
you can use pattern matching
request match {
case _ if (condition1 || condition2 || condition3) => false
case _ => request.process(); true
}
In Scala it is usual to return Option[value] rather than returning true/false and relying on side effects. And a Request object would normally be pure data, with processing done by an external function.
So a typical Scala function might look like this:
def func(req: Request): Option[Result] =
req match {
case Request(a, _, _) if condition1(a) => None
case Request(_, b, _) if condition2(b) => None
case _ =>
Some(processRequest(req))
}
You can just do a simple if else simplifying your conditions.
def func(request: Request) {
if (condition1 || condition2 || condition3)
false
else {
request.process()
true
}
}
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
}
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")
}
Swift 2's guide mentions that you can end program execution of an if statement. I personally have never used break with if-statement.
A break statement ends program execution of a loop, an if statement,
or a switch statement...When a break statement is followed by the
name of a statement label, it ends program execution of the loop, if
statement, or switch statement named by that label.
In what situation would one be using break in an if-statement? This language feature seems useless.
TEST:
if (true) {
break TEST
}
For example if you want to describe a number (with Strings) with reference to sets of numbers (even/rational/negative numbers) your code could look something like this:
if condition1 {
// code
if condition2 {
// code
if condition3 {
// code
if condition4 {
//code
}
}
}
}
You can achieve the same logic but without the nested ifs by refactoring it (using guard):
OuterIf: if condition1 {
// code
guard condition2 else { break OuterIf }
// code
guard condition3 else { break OuterIf }
// code
guard condition4 else { break OuterIf }
// code
}
// reads even better when breaking out of "do"
scope: do {
guard condition1 else { break scope }
// code
guard condition2 else { break scope }
// code
guard condition3 else { break scope }
// code
guard condition4 else { break scope }
// code
}
You might think that this can also be achieved with switch and fallthrough but this doesn't work with "normal" cases because it checks all conditions and if one condition is met all following conditions aren't even evaluated.
So the fallthough has to be called conditionally.
This does work but I isn't very readable not to mention its "beauty":
let x = 4
switch x {
case _ where condition1:
// code
if condition2 { fallthrough }
case _ where false:
// code
if condition3 { fallthrough }
case _ where false:
// code
if condition4 { fallthrough }
case _ where false:
// code
break
default: break
}
Using break with an if statement seems a bit contrived, and I can't think of a place where style would demand it. It does, however, save an extra level of indentation when skipping the latter portion of an if statement in an if-else clause, which can be useful for deeply nested loops.
In other languages, a popular (and/or controversial) idiom is to use labels for handling errors in deeply nested functions. For example, one might want to break out of a loop on error, like this:
func testBreak3() {
// doesn't compile!!!
let a = false, b = true, x = 10, y = 20, err = true
if !a {
if b && x > 0 {
if y < 100 {
if err {
break handleError
}
// some statements
} else {
// other stuff
}
}
}
return // avoid error handling
handleError:
print("error")
// handle the error
}
But in Swift (I'm using 2.0 as a reference), labels are different than with other languages; the above example doesn't compile for two reasons: The label isn't declared yet when it's used, and the label must be directly associated with a do, while, if, or case statement. Furthermore, break within an if or do statements requires that statement to be labeled. We can fix this as follows, although the changes make the solution less attractive due to additional tracking via the errorFlagged variable, making refactoring more attractive:
func testBreak() {
let a = false, b = true, x = 10, y = 20, err = true
var errorFlagged = false
nestedIf: if !a {
if b && x > 0 {
if y < 100 {
if err {
errorFlagged = true
break nestedIf
}
// some statements
} else {
// other stuff
}
}
}
// skip handling if no error flagged.
if errorFlagged {
print("error")
// handle error
}
}
I know this is old topic, but just now I used break and it was needed.
So my example
I have array of objects.
When user taps on a cell, i.parameter becomes True for the object in that cell.
I need to know when all the objects in the array have i.parameter = True , that's the condition to stop the game.
func forTimer(){
for i in array {
if i.parameter == false {
break
}
}
}
timer = Timer.scheduledTimer(timeInterval: 0.001, target: self, selector: #selector(forTimer), userInfo: nil, repeats: true)
Even if one i.parameter = false, I do not need to check the rest of the array.
This function is called every millisecond, so I will not have to check the whole array every millisecond.