Tuesday, April 01, 2008

Darren on Flex: The Boolean Value of Objects in Logical Expressions

Here's another one for the Flex (ActionScript) programmers out there. I come from the Java world and my first encounter with ActionScript has been through Flex - well actually, I dabbled in a bit of AS back at uni when I was playing with tweening and animations. Anyway, if you are like me in that respect, then you may not be familiar with all the language constructs, keywords and semantics there in. One thing, I have just discovered, are that 'non-boolean' variables have a boolean value that are evaluated when used in a logical expression. They go something like this (assigned object values):
  • null = false
  • 0 (zero) = false
  • false = false (...really!)
  • eveything else = true (... as far as I know)
Now there are a few cool things about this: Firstly, when you build up a logical expression, each object is evaluted for its boolean value prior to application of any logical operator. Based on the rules above, the logical expression will evaluate to true or false. It is my belief that this boolean value is obtained by coersion, from evaluating the logical expression i.e. in accordance with the rules above. So you maybe wondering what it is that's being coerced and from what? It seems the value that is coerced is the last evaluated object that determined the outcome of the expression. This is best explained through examples:
  • "aaa" && "aab" && "aac" = "aac"
  • "aaa" && null && "aac" = null
  • "aaa" && "aab" && 0 = 0
  • "aab" < "aac" = true
  • "aab" < "aaa" = false
  • 1 && 2 && 3 && 4 && 5 = 5
  • 0 && 1 && 2 && 3 && 4 = 0
Notice the lexical evalution. Next, it should be obvious by now that you can use logical expressions built in this way in decision constructs (if, for, while etc.) yet still assign them to variables of non-boolean type. For example:
    public function someMethod(... params):void
    {
        someInstanceArray = params || [];
    }
Before:
    public function someMethod(... params):void
    {
        if (params != null && params.length > 0)
        {
            // You can now safely access params[0] now
            ...           
        }
    }
After:
    public function someMethod(... params):void
    {
        if (params && params.length)
        {
            // You can now safely access params[0] now
            ...
        }
    }
Even After That:
    public function someMethod(... params):void
    {
        someObject = params && params.length && params[0] || new SomeThingYouNeed();
    }
Pretty cool ay. One thing that confused me (and thus descoped from understanding) was the following tests:
    trace("a" == true, " " == true, "" == true);
    trace("a" == false, " " == false, "" == false);
    trace(" " && "a", '" " && "a"');
    trace("" && "a", '"" && "a"');
which yields
false false false
false true true
a " " && "a"
 "" && "a"
Strange uh. I suspect other languages of the dynamic variety support these semantics e.g. Python; would be nice in Java. Comments welcome.