AS4 Feature proposal: tighten up implicit casting rules

! Warning: this post hasn't been updated in over three years and so may contain out of date information.

AS4 draftActionScript 3 (AS3) is a statically typed language with support for dynamic types. On the whole this flexibility neatly handles most development requirements in a sensible and reliable way. However its implicit conversion rules would benefit from being completely overhauled. Consider the following two code snippets:

Snippet 1:

Snippet 2:

In the first instance, the compiler will object to every line as we are attempting to implicitly cast between incompatible types. In the second instance, we are using a dynamic variable, which can take any type. Thus there are no errors.

Whilst AS3 is generally good with static types, it’s dynamic language past shows through at times. Other statically typed languages, such as C# and Java, apply a very sensible rule to implicit casting: implicit casting is allowed if there is no loss of information. Put simply, an 8 bit integer can be cast to a 16 or 32 bit one and to a floating point number. A 32 bit number can be cast to a 64 bit float (normally called a double). In addition, an object can be implicitly cast to an ancestor class type. The reverse cannot occur though without an explicit cast. Numeric values may be too large to store in the target variable and objects cannot be cast to child class types as they may lack functionality offered by those child class types.

AS3 by contrast adopts a very relaxed (some – including myself – would say sloppy) set of rules for implicit casting. Consider the implicit casting between uint and int. AS3 simply leaves the bits unchanged when converting between the two. So the following code:

Results in the following output:

The loose AS3 implicit casting rules aren’t confined to just numeric types though. Absolutely any type can be implicitly cast to a boolean. The following code demonstrates this in action:

If you were to run this code, the output would be:

So void, 0, null, undefined and “” are converted to false, whereas [], {}, “false”, -1 are all converted to true. This of course results in data loss in every case. Further, as absolutely any data can be converted to a boolean, any expression can be tested for true/ false in an if statement. In fact some otherwise well respected and knowledgable Flash developers seem to favour:

rather than

as a way of testing whether an object is null, despite the fact that o could actually be undefined, null, void, 0 or “”. This overloading of values that convert to false does of course give rise to some difficult to find bugs.

My proposal is for a tightening of implicit casting rules in ActionScript 4 (AS4). The rule for AS4 would be simple and would ensure no information loss when implicitly casting:

“Object o can be implicitly cast to o’ only if explicitly casting o’ back to o results in the value of o being unchanged by the cast and the implicit cast does not change the value.”

Assuming AS4 contains no new primitive types, this would limit implicit casts to:

  • unit -> Number
  • int -> Number
  • child class -> parent class/ implemented interface

The Flex Coding conventions coercion section (scroll down slightly from the link) is very muddled on implicit casting to boolean and unfortunately many folk follow these conventions. This language enhancement may therefore break a lot of existing AS3 code. The compiler probably should therefore include a strict-casting option, which could be set false to enable AS3-style weak implicit casting rules within the code. The compiler should default to strict-casting being true though to encourage the rewriting of existing code to the safer, and less error-prone, strict style.

Posted in AS4

11 thoughts on “AS4 Feature proposal: tighten up implicit casting rules

  1. @Robert,

    That’s a difficult one. As far as I can determine, there are no implicit casts to String. For example:

    will result in an error. Instead all types support the toString() method, so we could do:

    which is legal. However, As3 does implicitly call toString() when concatenating strings with other data types, which is sort of like an implicit cast. Maybe I’m being inconsistent, but I like that feature.

  2. >>In fact some otherwise well respected and knowledgable Flash developers seem to favour — if (o) — rather than — if (o != null) — as a way of testing whether an object is null, despite the fact that o could actually be undefined, null, void, 0 or “”.<<

    I hope you're not trying to stick that on me. Yes, I had that bug you linked to. However, I specifically tweeted a few days ago:

    'Lesson from #as3signals bug: with foo:Object, don't rely on "if (!foo)". foo could be anything, including 0.'

    http://twitter.com/robpenner/status/10734479787

  3. What do you prefer for checking that a String isn’t empty?

    if (text != null && text.length > 0)

    if (text != null && text.length)

    if (text && text.length)

    if (text)

    These all do the same thing, far as I can see. If text is “0”, it still works.

  4. > o could actually be undefined, null, void, 0 or “”.

    I did some reading and testing on this. It seems an Object cannot “be” void or undefined in AS3.

    If you try to assign void to an Object, you’ll get a compile error:

    1067: Implicit coercion of a value of type void to an unrelated type Object.

    The docs say: “The void data type contains only one value, undefined.”:

    http://help.adobe.com/en_US/ActionScript/3.0_ProgrammingAS3/WS5b3ccc516d4fbf351e63e3d118a9b90204-7f88.html

    Your voidFunc doesn’t literally return void; it returns undefined:

    trace(voidFunc() === undefined); // true

    You can assign undefined to an Object, but it’s implicitly converted to null (data loss!). So an Object cannot be undefined, either. Only variables that are untyped or typed to * can be undefined.

  5. If a variable is declared as a complex type, it’s either null, or a valid instance. The complex type can’t be 0 or an empty string. It seems there are only two possibilities:

    Boolean(null) == false
    Boolean(validInstance) == true

    So why should I waste my time with this?

    if (myComplexType != null)

    I might as well do this:

    if (myBoolean == false)

  6. @Robert,

    You offer a bunch of ways of checking if a string is empty, but miss what to me is the obvious way of doing it:

    If I declare a variable to be of type Object, there is still a range of values it can take that cast to false:

    A “complex type” could be Object, in which case

    will fail for null, 0 and “”. It could be String, in which case

    will fail for null and “”. It could be Number, in which case

    will fail for 0, as null is implicitly cast to 0 for Number. It could be some other class, in which case

    will fail for null. So whilst the latter is a reliable test of null, is it really sensible to have a rule that applies to otherClass, that cannot be applied to Object or String and that tests for something else for Number?

    So “wasting your time” with

    or to be really safe

    to protect against mistyping “==” as “=” and doing an assignment is actually good practice as you are far less likely to accidently do

    if in the habit of always explicitly testing for null.

Comments are closed.