August 2004 Archives

Terms like inline, anonymous, named, standard, etc. get thrown around a lot but are not always used correctly. Hopefully this post will shed some light of some of the function terminology that you may have come across in your ActionScript adventures.

  • Named Functions

    A named function is of the form:

    function foo(param1, param2, etc) {
            // do stuff here
    }
    

    Named functions, no matter where they are defined on a frame, are placed at the front of the actions for a frame at compile time. Therefore, you can forward reference them. That is, I can call "foo()" before I defined the foo function and the function will still execute.

    Named functions can only define functions in the timelines that they are written in.

  • Anonymous Functions

    An anonymous function is defined like this:

    bar = function(param1, param2, etc) {
            // do stuff here
    }
    

    Anonymous functions are interesting beasts. Unlike named functions, when you create an anonymous function there is no way to reference the function via code. We can get around this with function literals.

    When the function is created it returns a reference to itself. In the example above, we set a variable "bar" to reference the anonymous function we create.

    Now, whenever bar is called, the anonymous function that it references will execute. Unlike named functions, anonymous functions cannot be forward referenced. If I make a call to bar before I set bar to reference the function, the call will fail.

    When creating an anonymous recursive function, the function can reference itself by using the arguments.callee property. Consider this example:

    // classic factorial recursion example
    factorial = function(n) {
            if (n <= 1) {
                    return n;
            } else {
                    return n*arguments.callee(n-1);  // call ourself to recurse
            }
    }
    

    Note that in the above example, we can replace arguments.callee with factorial and the example will still work. However, there are times in which we don't have a variable to call the function with. In those cases, arguments.callee is the only solution. An example of this might be passing an anonymous function as a parameter to another function.

    Function literals can define functions in any timeline/object, provided the path exists at the time of definition. For instance, to create a function inside of an object, we have to use a function literal like this:

    obj = new Object();
    obj.foo = function() {
        return "bar";
    }
    
    trace(obj.foo());  // bar
    
  • Inline Functions

    Inline functions do not exist in Flash. This is a common misconception - people tend to refer to function literals as inline functions, which is incorrect.

    The basic idea behind inline functions is to improve execution speed at the sacrifice of program size. Behind the scenes, the inline concept works something like this...

    When a function is created, a block of data is created containing the function code. Then, when a program executes a function call, the program stores is current state, jumps to the location of the function block, executes the code it finds there (the function body), jumps back to where it left off in normal execution and restores its previous state.

    Because of the state shuffling and the extra jumps to the function location, there is overhead associated with any function call. Inline functions are a way around this.

    Instead of jumping to a block of memory, an inline function will just insert the function code directly into the program ("in line"). The code no longer has to jump to the function block and deal with remembering it's current state - it can just continue execution normally. This, however, leads to larger program sizes.

    Image I call a function 10 times. With a function, the code is only inserted into the program 1 time and referenced 10 times through the 10 different function calls. Compare that to inline functions where the function code is inserted into the program 10 times at each different function call.

I realize that a lot of this information is old hat to a lot of people, but I still see some misuse of terms. Hopefully this post helps to clear things up a little for everyone...

If you've ever passed a struct from ColdFusion to Flash via Flash Remoting, you've probably noticed that all of the keys for the struct come into Flash as uppercase. In the past, this wasn't that big of a deal, but when Flash Player 7 came around with case-sensitivity, some people started to encounter problems. Here's the simple workaround...

Consider the following code:

<cfcomponent>
  <cffunction name="getSomeData" returntype="struct" access="remote">
    <cfset oData = StructNew() />
    <cfset oData.key1 = "example 1" />   <!--- converts to KEY1 --->
    <cfset oData["key2"]= "example 2" />   <!--- preserves case --->
    <cfset StructInsert(oData, "key3", "example 3") /> <!--- preserves case --->
    <cfreturn oData />
  </cffunction>
</cfcomponent>

Note that accessing a struct in the "usual" way with dot notation will convert the key to all uppercase. By using array (bracket) notation, you can preserve the case of the key. Additionally, if you use the StructInsert function you can also preserve the case of the key.

I hope this post saves someone some debugging time in the future. This question recently came up on a mailing list, so hopefully google will find this post and make the answer easier to locate. :-)

Flash Quirk: Disabled buttons still broadcast click

| 9 Comments

The official status on this one is "Not a Bug." This behavior was done by design, but it's a little bit counter-intuitive and not consistent with what I've experienced in other languages. I wanted to mention it here as another example of a Flash Quirk.

Consider the following code: (drag a v2 button onto the stage and give it an instance name of "testBtn")

import mx.controls.Button;
import mx.utils.Delegate;

var testBtn:Button;
var onClick:Function = function():Void {
	trace("testBtn clicked!");
}

// call onClick whenever testBtn is pressed
testBtn.addEventListener("click", Delegate.create(this, onClick));

// "press" the button programmatically
testBtn.onRelease();

When the movie is tested, you'll see this code work perfectly. The button press is simulated via ActionScript, and we get the expected trace outpout. Why would you want to simulate a button press through code? The classic example is implementing keyboard shorcuts that invoke button methods.

Now, add this line BEFORE the onRelease call:

// disable the button
testBtn.enabled = false;

Now run the modified code and notice the results. The button was still pressed, even though it was disabled.

Whenever I disable a JButton in Java or a Button in C# and attempt to programmatically press the button (doClick or PerformClick, respectively), the "click" event is not generated. I expected the same behavior out of Flash, but we all know Flash is a very different beast and somehow I'm not surprised.

The workaround is simple, just change the onRelease call to this:

// "press" the button programmatically, but only if it's enabled
if (testBtn.enabled) testBtn.onRelease();

Still though, that just feels wrong to me.

What do you think - is this a bug, or just another quirk? To me, it's a bug since it's unexpected behavior. However, it's officially not a bug (which makes it a quirk) and I don't think Macromedia is going to do anything about it.

Feedback on CFC-Based Security System

| No Comments | No TrackBacks

Jim Davis is looking for some feedback on a CFC-based security system that he has recently implemented (open source). If you use ColdFusion and have some time to spare, kick this thing around a bit and give him some feedback to help make the first official release a solid one.

Here is his original announcement:

Flex.org - The Directory for Flex

Archives