Structure or syntax for empty if/elsif/else block in perl - perl

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();

Related

JS timeout causes eval exception

For some reason, one of my JS files is triggering an unsafe-eval Content Security Policy violation on my site. I thought this odd because there is no eval() anywhere in the file. The error happens on the following line:
setTimeout(callSpecific(), (lengthMF * (number.length + 2)));
The only thing I can see here is the arithmetic on the RHS that sets the timeout value. So, I tried:
setTimeout(callSpecific(), (parseInt(lengthMF) * (parseInt(number.length) + 2)));
Same thing. The variables themselves are not even strings - they are defined as:
var lengthMF = 150;
var number = ""; // yes, this is a string but number.length is not!
Why is this triggering a CSP violation? I have other setTimeout()s on the page and this seems to be the only problematic one. The weird thing is replacing the arithmetic expression temporarily with a constant (e.g. 50) does not cause the issue to go away.
If it's necessary, callSpecific() looks something like this:
function callSpecific() {
if (number == 0) {
operatorRing();
} else if (number.length == 2 && number.charAt(1) == 0) {
playReorder();
} else if (number.length == 3) {
//
} else if (number.length <7 || number.length > 11) {
//
} else if (number.length == 11 && (number.charAt(4) == 1 || number.charAt(4) == 0)) {
//
}
}

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
}

Are "&&" and "," the same in 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")
}

Swift alternative to write a lot of bools

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
....
}

Multiple else if conditions true

I have multiple elsif conditions in a else if statement.
What is the flow of the statement if multiple conditions are true? So in the simplistic example below which serves as a demonstration only, is the the second elsif condition ever reached?
my $i = 1;
if ($i == 1){
}
elsif (i == 2){
}
elsif (i == 1){
}
else{
}
Easy to try:
use feature ":5.10";
my $i = 1;
if ($i == 1) {
say "A"; # this is the only branch executed
} elsif (i == 2) {
say "B";
} elsif (i == 1) {
say "C";
} else {
say "D";
}
Each elsif is only considered if the previous conditions did not succeed. You can see that the comparisons are not even tried:
if ($i == 1) {
say "A";
} elsif (i == 2/0) { # This doesn’t blow up since the comparison is never tried
say "B";
} else {
say "C";
}
The system starts at the if statement and checks the condition. If it is true, it executes the body of the statement and then skips over the remaining else and else if statements. If it is false, it moves down to the first else if statement listed. The same process occurs: check condition, if true execute body and skip over remaining else if and else statements; if false skip down to the next else if statement.
In short: the else if statements are chosen in order from the top down. So if you have two else if statements that would both be true, only the top one would be executed.
First match will win other esle/elsif blocks are skipped.
No, the second elsif block will not be reached.