What is the best/easiest way to use nested switch/case statements? - actionscript-3

What is the better practice of the following two switch/case statements?
Is there an easier way (less code) to do this?
switch (myValue)
{
case 1:
{
methodFor1();
break;
}
case 2:
case 3:
{
methodFor2or3();
if (myValue == 2)
methodFor2();
if (myValue == 3)
methodFor3();
break;
}
}
...or...
switch (myValue)
{
case 1:
{
methodFor1();
break;
}
case 2:
case 3:
{
methodFor2or3();
switch (myValue)
{
case 2:
{
methodFor2();
break;
}
case 3:
{
methodFor3();
break;
}
}
break;
}
}

switch (myValue)
{
case 1:
methodFor1();
break;
case 2:
methodFor2or3();
methodFor2();
break;
case 3:
methodFor2or3();
methodFor3();
break;
}
Why all the hassle just to avoid repeating methodFor2or3() once?

One more alternative:
switch (myValue)
{
case 1:
{
methodFor1();
break;
}
case 2:
{
methodFor2or3();
methodFor2();
break;
}
case 3:
{
methodFor2or3();
methodFor3();
break;
}
}

Since functions are first class objects in actionscript3, you could build a hash of values to functions, like so:
var myDict:Dictionary = new Dictionary();
myDict[1] = methodFor1;
myDict[2] = methodFor2;
function handleStuff(myVal:Number):void{
var myFunction:Function = myDict[myVal];
myFunction();
}
hope this helps!

In my programming of switch statements, I aim for making each case have at most one line of code + a break;. This is because switch can quickly get big and complicated, and my brain isn't good at complicated.
So, in your case, I would write:
switch (myValue)
{
case 1:
{
methodFor1();
break;
}
case 2:
{
methodFor2();
break;
}
case 3:
{
methodFor3();
break;
}
}
and then make methodFor2 and methodFor3 each call methodFor2or3.

If there is only one (fairly simple) line in common between the two cases (as the function call in your example), then I prefer to double that line just for the sake of better readability. Otherwise, it's a matter of taste. I tend to prefer if conditions inside the case statements, because that way you can't confuse the various levels.

How about something more like:
var method:String = "methodFor" + String(value);
this[method]();
if (value == 3) methodFor2or3();
You might think of splitting out the or3 call if it's simpler code you want:
switch (value) {
case 1: methodFor1(); break;
case 2: methodFor2(); break;
case 3: methodFor3(); break;
}
if (value == 2 || value == 3) methodFor2or3();

When you're dealing with programming flow of control issues, "less code" isn't really the attribute you want to optimize on. It's far better with structural issues to bend your code towards being simple and readable.
So for the above, the first option isn't bad, although the 'flow-through' case for 2 can easily be missed. Better is to just do the parent switch on a 1 or 2, then in the second case call another function that handles the sub-cases (formally 2 and 3), and make this driven by a different (sub-case) variable (to insure that you're not overloading the 'meaning' of the initial 'value' variable.
Philosophically, all three cases are part of the same switch, OR they are not. If they are, then they should be treated equally (and indistinguishably from each other). If they are not, then they should be driven by two separate variables and handled in two separate functions. Trying to save 'bandwidth' by combining them complicates thing unnecessarily.
Paul.

I am answering assuming that you know the example case you gave is contrived and is better written in other ways. If you just want to know if it's best to nest switches or to use if-else within a switch, it totally depends on taste and the individual situation.
In my opinion, the fact that your block is inside a switch makes no difference. If the logic would be better served by a switch, use a switch (nested or not). If it would be better served by an if-else, use that.

Related

Opposite of 'else' during a switch or conditional

I'm wondering if any programming language has an operator like so (ALWAYS is a placeholder--I'm asking what language has something like ALWAYS)
if a
doAStuff()
else if b
doBStuff()
ALWAYS
//runs if a or b is true
win()
else
doElse()
Basically, the opposite of else. It runs if something else in the statement ran.
logically, it would be like this
always = true
if a
doA()
else if b
doB()
else
always = false
doElse()
if always
win()
Does any language have that logic built into a keyword, such as ALWAYS from the first example?
Not really 'language-agnostic'. More like 'find-my-language'. With Forth and Lisp you can add such a construct naturally to the language, and it will work just like existing constructs. I'm not aware of any language that has it by default. If you have a less extensible language than Forth or Lisp, then the natural ways to do this are to use a local function (if you have first-class functions) or to set a flag as you show, or else to factor the code such that both conditions can be treated as pairs without a lot of repetition.
So, in JavaScript:
;(function() {
function both() { win(); more stuff, potentially }
if (a) { doA(); if (b) both() }
else if (b) { doB(); if (a) both() }
else neither()
})()
At upon reading that, it should be clear that the 'both' case is never going to happen in that second block. So this simplifies to:
;(function() {
function both() { win(); more stuff, potentially }
if (a) { doA(); if (b) both() }
else if (b) doB()
else neither()
})()
Which doesn't seem worth the effort. So it seems even less worth a language feature. Why not go further and write this?
if (a) { doA(); if (b) { win(); more stuff, potentially } }
else if (b) doB()
else neither()
If b is an expensive test, just save the result of it. If b must not be tested before a, save both results. Obviously, both tests must always be run anyway.
;(function() {
var a = testA(),
b = testB()
... as above ...
})()
As for the last option, "factor the code such that both conditions can be treated as pairs", what you're looking for is:
if (a && !b) doA()
if (!a && b) doB()
if (a && b) { doA(); doB(); win() } // or no doB() if you really want that
if (!a && !b) neither()
With else if if you like. I'd prefer this option actually in a pattern-matching language. Mercury will even throw an compile-time error if you forget one of the four possible outcomes.
Not sure if this is what you're looking for, but a simple do-while loop will ALWAYS run at least once in Java.

nested ternary operator vs nested if else, which is better in readability purpose

I found code in code review which was written by my team member. It contains nested ternary operator. I told him to use if else if there is more than one nesting for readability purpose. We had argue on that.
following is code
ColorEnum color = opacity == Opacity.FIVE? ColorEnum.BLACK :
opacity == Opacity.TEN? ColorEnum.WHITE :
opacity == Opacity.FIFTY? ColorEnum.RED :
opacity == Opacity.TWENTY? ColorEnum.BLUE :
opacity == Opacity.FIFTEEN? ColorEnum.PURPLE : null;
And this code is changing as new configurations come.
So What is better here? ternary operator or if else?
Just reformatting your code makes it quite clear:
ColorEnum color =
opacity == Opacity.FIVE ? ColorEnum.BLACK
: opacity == Opacity.TEN ? ColorEnum.WHITE
: opacity == Opacity.FIFTY ? ColorEnum.RED
: opacity == Opacity.TWENTY ? ColorEnum.BLUE
: opacity == Opacity.FIFTEEN ? ColorEnum.PURPLE
: null;
LISP adopts the cond construct which has both the same structure and the same semantics, and is considered good practice. As an aside, Clojure also supports a form which tests the value of a single expression with a single predicate applied to different values (one for each clause) and calls it condp—that would be a perfect match for your use case.
The idiom with the ternary operator has the advantage over an if-else cascade for being an expression so you need only a single statement to assign it to the variable. if-else will force you to pull the assignment into each then clause, introducing more boilerplate and more opportunity to fail on correctness.
A switch statement could also be considered as an alternative, but it would have the following deficiencies:
like if-else, it is not an expression;
you are restricted to just different constant values of a single expression (the type of the expression being quite constrained, too).
it's prone to bugs due to the boilerplate break missing somewhere.
I would suggest to use switch statement. It would be more readable than ternary and if-else.
switch(opticity)
{
case Opticity.FIVE: color = ColorEnum.BLACK;
break;
case Opticity.TEN: color = ColorEnum.WHITE;
break;
case Opticity.FIFTY: color = ColorEnum.RED;
break;
....
default: printf("Error message\n");
}
For this purpose, probably a switch-case statement would be best in terms of readability.
Go with switch.
I've a thumb rule which I consistently follow (Although not hardset)
1) Only one conditional evaluation, go with ternary operator
2) Two conditional check, go with if(){} else if(){ } else{} construct
3) Three or more go with switch ladder
“Programs must be written for people to read, and only incidentally for machines to execute.”
― Harold Abelson, Structure and Interpretation of Computer Programs
As others have mentioned, a switch would be a good alternative. To reduce boilerplate code (breaks, assignments), I would further recommend putting the switch into a dedicated method:
(All examples are in C#)
public ColorEnum OpacityToColor(Opacity opacity)
{
switch (opacity)
{
case Opacity.FIVE:
return ColorEnum.BLACK;
case Opacity.TEN:
return ColorEnum.WHITE;
case Opacity.FIFTY:
return ColorEnum.RED;
case Opacity.TWENTY:
return ColorEnum.BLUE;
case Opacity.FIFTEEN:
return ColorEnum.PURPLE;
default:
throw new System.ArgumentOutOfRangeException("opacity");
}
}
// Elsewhere
ColorEnum color = OpacityToColor(opacity);
If your language has a neat dictionary/map initialization syntax (e.g. Python, C#), you could also use that for a very concise and clear notation:
public static readonly Dictionary<Opacity, ColorEnum> ColorByOpacity =
new Dictionary<Opacity, ColorEnum>
{
{Opacity.FIVE, ColorEnum.BLACK},
{Opacity.TEN, ColorEnum.WHITE},
{Opacity.FIFTY, ColorEnum.RED},
{Opacity.TWENTY, ColorEnum.BLUE},
{Opacity.FIFTEEN, ColorEnum.PURPLE}
};
// Elsewhere
ColorEnum color = ColorByOpacity[opacity];

Compact if/else statement [AS3]

Really simple question, I just wanted to know if there was a way to write if/else statements with fewer characters, for example I can create an if statement with either:
if (season == "autumn") {
tree.gotoAndStop ("brown leaves");
}
or:
if (season == "autumn") tree.gotoAndStop ("brown leaves");
This uses much less space and makes my code look much prettier. With an if/else statement my options seem to be either:
if (season == "autumn" || season == "winter") {
tree.gotoAndStop ("brown leaves");
} else {
tree.gotoAndStop ("green leaves");
}
or:
gotoAndStop((season == "autumn" || season == "winter")
? "brown leaves" : "green leaves");
Though the second approach isn't always ideal. Do you know any alternatives?
As far as writing your code in a terse manner, you can use all of the following techniques to manually minify your code, but this is a terrible design decision and will likely lead to headaches and/or bodily harm in the future. Don't say I didn't warn you.
if-else:
if (foo) {
bar();
} else {
baz();
}
becomes:
foo?bar():baz()
if:
if (foo) {
bar();
}
becomes:
foo&&bar();
if-not:
if (!foo) {
bar();
}
becomes:
foo||bar();
if with multiple statements:
if (foo) {
bar();
baz();
fizz();
buzz();
}
becomes:
foo&&(bar(),baz(),fizz(),buzz());

Flash Actionscript 3 Bug? Using an int and negative numbers in a switch/case

Running this code
var myValue1:int = 2;
switch (myValue1)
{
case -3: trace(myValue1 + " == -3"); break;
case -2: trace(myValue1 + " == -2"); break;
case -1: trace(myValue1 + " == -1"); break;
case 0: trace(myValue1 + " == 0"); break;
case 1: trace(myValue1 + " == 1"); break;
case 2: trace(myValue1 + " == 2"); break;
case 3: trace(myValue1 + " == 3"); break;
default: trace(myValue1 + " is unknown"); break;
}
var myValue2:int = -2;
switch (myValue2)
{
case -3: trace(myValue2 + " == -3"); break;
case -2: trace(myValue2 + " == -2"); break;
case -1: trace(myValue2 + " == -1"); break;
case 0: trace(myValue2 + " == 0"); break;
case 1: trace(myValue2 + " == 1"); break;
case 2: trace(myValue2 + " == 2"); break;
case 3: trace(myValue2 + " == 3"); break;
default: trace(myValue2 + " is unknown"); break;
}
gives this output:
2 == 0
-2 is unknown
(Compiled in Flash Builder 4.7.0.349722, running on Flash 11.5.502.149. Running in Windows 7 SP1, Firefox 18.0.2)
The following changes all fix the above problem, giving the correct output:
Changing the value-type to Number.
Removing the negative-number case statements.
Changing the case statements to use int-variables rather than literals... unless those variables are also const, in which case it stays broken!
Changing myValue2 = -1 gives the output -1 == -3, which is equally wtf-ish.
Clearly this is a bug, but... what causes it? Is there some subtle nuance of using int or negative numbers in case-statements that I don't understand? Is my code somehow wrong? Or is this simply an issue with the bytecode-compiler in Flash Builder?
I don't think you will find a concrete answer to this question.
What I can offer is a confirmation of the AS3 compiler bugginess.
I spent quite some time trying to resolve similar 'magical' errors and came up empty.
One such example is a For and While loops skipping the first or last item in an Array for no apparent reason while a Foreach looped worked just fine.
To me the most plausible reason for that is an error in memory management.
It might also be hardware related since the frequency of such things happening was higher on some machines that I or my colleagues worked on.
What I think is that some 'invisible' conditions are met e.g. order of performed operations ( you could try putting some dummy code in between the var declaration and the switch or maybe assigning the var value couple more times, just to 'jog the memory') that combined with the error-prone compiler mess up the memory addressing and your switch thinks its compering two integers while in reality it got a different value from the memory.
You can probably force the compiler's hand by converting the original value to a String and making your cases into String values.
switch( String(value) )
{
case "-3": /*do something*/; break;
case "-2": /*do something*/; break;
case "-1": /*do something*/; break;
case "0": /*do something*/; break;
case "1": /*do something*/; break;
case "2": /*do something*/; break;
case "3": /*do something*/; break;
default: break;
}
This is simply an issue with the bytecode-compiler in Flash Builder.
Clearly, your syntax is fine; there are literally hundreds of known issues with the compiler dating back to 2005 that are still open or unresolved.

same button, each click performs another function... HOW?

I have a website that has multiple languages, currently the language bar is displayed along the top of the site with a button for each language. What I would prefer is one button, click it once, the button image changes to a union jack flag, and english is called, press it again, and the button image changes to french, and the french language is called, etc etc..
Is this one button, multiple calls possible? can anyone give me a good place to start looking in to this?
Yes, it is possible.
Your html would look something like this:
<button id='changeLang' onclick='changeLang()'></button>
(Remember to set this to your default to begin with)
and your javascript:
var counter = 0;
function changeLang(){
var buttonDetails = document.getElementById('changeLang');
buttonDetails.innerHTML = "";
switch(counter){
case 0:
buttonDetails.innerHTML = "<img src='unionJack.png' />English";
counter +=1;
break;
case 1:
buttonDetails.innerHTML = "<img src='frenchFlag.png' />French";
counter +=1;
break;
case 2:
//continue like above
default:
counter = 0;
changeLang();
}
}
If you ever need another language, just add it to the switch.
Alternatively, change the case code to:
case 0:
buttonDetails.src = "unionJack.png";
counter +=1;
break;
And remove the line that says buttonDetails.innerHTML = ""; if all you want is an image.
To call a function to change the language you would simply add a function call to one of your switch cases like so:
case 0:
buttonDetails.innerHTML = "<img src='unionJack.png' />English";
counter +=1;
foo(bar); //just add your function call
break;