Win A Free Book
A while back, I had a little piece on getting rid of conditional statements. Since that time, I’ve been writing scripts that have reduced the number of conditionals significantly, and we thought it might be fun to have a little contest with the prize, a free, signed copy of our design pattern book.
Alternatives to Conditional Statements
In thinking about this issue, the Boolean is the key–much in the same way as it is with conditional statements. One way to handle a simple if..else conditional is by multiplying a Boolean changed to an unsigned integer. For example, if you want to use the color black and some other color to signify a state you could have something like the following:
1 2 3 4 5 6 7 | var clr:uint=0x00aa00; var cond:uint; var good:Boolean; good=e.info.code=="NetConnection.Connect.Success"; cond=uint(good); clr=clr * cond; //Now the color value can be passed as a parameter to a "connection light." |
The clr variable can now be green or black. If the connection is successful, the cond variable resolves to 1; otherwise it resolves to 0. If you multiply by 0, the results are always 0. Also, 1 multiplied by any number always resolves as the original number. Since the color black is 0 (0×000000), if the connection is not successful the color black is generated, but if it is successful and generates a 1, it multiplies the green value (0×00aa00) by 1 and gets 0×00aa00. The alternative is something like:
1 2 3 4 5 6 7 8 9 10 | var clr:uint if(e.info.code=="NextConnection.Connect.Successful") { clr=0x00aa00; } { else { clr=0x0000; } |
Of course a ternary would have been even quicker–coding wise, but it probably has a similar under-the-hood cost and encapsulation break out.
Non-Conditional Switch Statement
In playing around with conditionals, I decided to see if I could create a switch-like statement–or set of statements that worked like switch. The following is what I came up with:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | package { import flash.display.Sprite; import flash.display.Shape; public class NoConSwitch extends Sprite { private var freeSwitch:String; private var freeSet:Array; private var freeCase:uint; private var rec:Shape; public function NoConSwitch () { freeSet=[0x0000, 0xaa0000,0x00aa00,0x0000aa,0x800080]; freeSwitch="Green"; freeSwitch=freeSwitch.toLowerCase(); freeCase=uint(freeSwitch=="red")*1; freeCase+=uint(freeSwitch=="green")*2; freeCase+=uint(freeSwitch=="blue")*3; freeCase+=uint(freeSwitch=="purple")*4; doRectangle (freeSet[freeCase]); } private function doRectangle (clr:uint) { rec=new Shape(); rec.graphics.beginFill (clr); rec.graphics.lineStyle (.25,0x000000); rec.graphics.drawRect (80,40,400,300); addChild (rec); } } } |
Granted that my non-conditional switch statement may not have the flexibility of a standard switch statement, but it does the job I’d normally do with a switch statement.
Back to the contest
I’m sure that anyone reading this can come up with more ways to get around using conditional statements. So to enter the contest, just use the Comments section of this Post to respond with an idea of your own (including a working example in ActionScript 3.0) that shows an alternative to a conditional statement that does the same thing without using a conditional statement. You can enter as many times as you want by January 31, 2008. On February 1, we’ll announce the winner and send a book to you.

The Unconditional Contest by William B. Sanders, unless otherwise expressly stated, is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.

Bill Sanders
I think one of the best ways to avoid conditionals is by mapping the possible conditions to specific data. Here’s a simple example:
Or you could go all out and map functions themselves:
This looks kind of ugly in this simple example, but is essentially what things like service locators do.
Just realized I left a conditional in there. You can substitute the if with a try catch, like so:
Keith:
Some guys at Realeyes did some testing, and found that try statements were much slower than any other statements. If we’re just trying to get rid of if statements, but still need to check for null, a while(keys[event.keyCode] != null) would give much better performance.
However, try and while statements used in this fashion are the same thing as a conditional, in an academic sense, so it may be better to initialize every possible key value upon initialization to ensure that there is no null value. This would greatly simplify the logic.
omg bill
are you serious?? sorry, but this is the worst code i’ve ever seen. :(
this is really bad practice and certainly not the intention of the state design pattern.
Dusty,
It’d be great if you guys at Realeyes provided an entry in our Unconditional Contest.
Bill
Hi Robs,
I may have skewed the whole idea of substituting alternatives to conventional conditional statements with some other kind of thinking. I do not believe I ever said that this was an intention of State Design Patterns. Rather, they stood as a common example where state classes with a full set of different states could be found without relying on conditional statements. Jonathan Kaye had a great comment on that.
For a second (or even longer) forget about State DPs. Rather, consider problem-solving without using conditional statements. What are some different ways you could do that? This is a heuristic exercise to come up with better solutions and algorithms.
As for the “worst code” you’ve ever seen–that’s not the point. See if you can create any kind of statement that works to have the branching effect of a conditional without using a conditional statement. It’s harder than you may think.
Thanks,
Bill
I guess some characters (greater than, less than, and,..) are eliminated from my code which seems to be due to avoiding XSS. I have uploaded the .fla :
http://rapidshare.com/files/82584763/roozbeh.fla.html
I was looking at this line of code that attempts to evade conditionals:
It does not evade conditionals, it just simply rephrases conditionals. It still contains a “==” and that is a conditional. The correct way to express that code is this:
You gain nothing by trying to stuff lots of functionality on a single line of code. In fact, by putting on one line of code, the program will always execute 2 conditionals (checking for upbtn and downbtn), but by using the “if” statement, it will only check the downbtn if the upbtn conditional is false. And it does not go through the extra step of typecasting a boolean into an integer.
A better way yet is to create a different listener function for up vs. down so that you really can eliminate the conditional.
Hi Harry,
Your visit is an honor, and I’m glad you could drop by.
I’m probably at fault for not clarifying better my attempt to look at problem solving without using conditionals. It certainly was not to save coding (or stuff less or more in a line.) One of the criticisms of the State DP is that it takes a lot of classes and coding in the absence of conditional statements. The whole exercise is a heuristic one to create better algorithms which I picked up in an OOPSLA conference.
More interesting is your comment about the equality operator being a conditional. I’ve always considered it a Boolean, but in an expression, I suppose it might be a conditional.
var x:uint = 5;
var w:uint = 7;
var z:uint = 5;
x==w evaluates to false
x==z evaluates to true
A conditional would be:
However, you’re saying that the equality operator performs a conditional, and it seems to. In effect the equality operator is saying:
“If a and b are equal, then send out true, else, they get a false”
This feature is masked because the equality operator is often part of the if/else statement.
Nice.
Bill
just tell me what part of the code you think somehow uses a condition and I will eliminate it :)
Ok, sorry for so many posts…. yeah its the code of a maniac hehe… anyways I i tried & fixed it .. realized I didnt need alot of things…Its a great exercise in that it makes you think…it really is not easy…
AS3 example I edited from tutorial….
package{
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
//abstract class
public class AnimatingProperties extends Sprite{
private var _sprite:Sprite;
private var _k:Number=0.1;
private var _damp:Number=0.9;
private var _scaleVel:Number=0;
private var _targetScale:Number=1;
private var _click:Number=0;
public function AS3CB(){
_sprite = new Sprite();
_sprite.graphics.beginFill(0×0000,100);
_sprite.graphics.drawRect(-50,-50,100,100);
_sprite.graphics.endFill();
_sprite.x=100;
_sprite.y=100;
addChild(_sprite);
addEventListener(Event.ENTER_FRAME,onEnterFrame);
_sprite.addEventListener(MouseEvent.CLICK,onClick);
};
public function onEnterFrame(event:Event):void{
_scaleVel += (_targetScale – _sprite.scaleX) * _k;
_sprite.scaleX += _scaleVel;
_sprite.scaleY = _sprite.scaleX;
_scaleVel *= _damp;
};
public function onClick(event:MouseEvent):void{
/**———TRYING TO AVOID USING IF ELSE ETC————**/
_click++;
var b = _click >= 2;
_targetScale = _targetScale * 2 – .5
while(b){
_targetScale -= _targetScale -= .5 * 2;
_click = 0;
break;
}
};
}
}