Monday, February 25, 2008

Flex MXML, Functions and Nested Functions

In my previous post Anonymous Functions in Flex, I mentioned about the inconsistent behaviour of nested functions. I decided to dvelve deeper and see if it was a bug or if i was missing something. I started out with the language specification, which was very disappointing, still, had some information on how functions in actionscript behave.

The following lines are taken from the specification document :

/**********************************************************************************

Function objects have a property named prototype whose value is used to initialize the intrinsic delegate property of the objects it creates. The prototype property has a default value of a new instance of the class Object. Building on the previous example:

function A() { this.x = 10 }
function B() {}
B.prototype = new A
var o = new B
trace(o.x) // traces 10

The value of o is an instance of B, which delegates to an instance of A, which has a property named x with value of 10.

Constructor methods inside of a class are also used to create objects. But, unlike constructor functions, constructor methods create objects with a set of fixed properties (traits) associated with its class and a delegate that is also an instance of its class.

class A {
var x
function A() { this.x = 10 }
}
var o = new A
trace(o.x) // traces 10

There are some subtle differences between the preceding example and the one involving a function constructor:

  • x is a fixed property of each instance of A rather than a dynamic property.
  • A.prototype is an instance of A rather than an instance of Object.
  • The expression A(expr) does not call the function A defined in class A. It results in an explicit conversion of the value of expr to the type A.

Class methods are functions that are defined with the static attribute inside of a class definition. A class method cannot be used as a constructor and does not define the this reference. Class methods are in the scope of the class object in which they are defined.

Instance methods are functions that are defined without the static attribute and inside a class definition. Instance methods are associated with an instance of the class in which they are defined. Instance methods can override or implement inherited class or interface methods and always have a value bound to this.

The value of this in an instance method is the value of the instance the method belongs to.
************************************************************************************/
Having said that, consider the example below : (The examples below have syntax errors, i had to do so, r else the page would not display these tags properly, please correct them, if you r copy/pasting)


mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute">

mx:Button id="ti" click="getText()" label="uhuh"/>
mx:Script>
ADD CDATA TAG HERE WHEN COMPILING
import mx.core.UIComponent;
import mx.controls.Alert;

private var global_var:String = "global_var";

private function getText():void
{
Alert.show("Level 1 : "+global_var+"\n\n"+this.ti.label);
var inner1:Function = function():void
{
Alert.show("Level 2 : "+global_var+"\n\n"+this.ti.label)
var inner2:Function = function():void
{
Alert.show("Level 3 : "+global_var+"\n\n"+this.ti.label);
}
inner2();
};
inner1();
}

]]>
/mx:Script>
/mx:Application>


In the above example, getText() is a instance method, and the flex compiler sets this method's this reference to the Application instance. So, Level 1 is good, but the functions inner2 and inner3 are not instance methods and their this reference is not set to anything, we have to set it.
And how do we do it? We do it by calling the function, specifying the prototype object/target object for that function using call method. Below is a working example.


mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute">

mx:Button id="ti" click="getText()" label="uhuh"/>
mx:Script>
ADD CDATA TAG HERE WHEN COMPILING
import mx.core.UIComponent;
import mx.controls.Alert;

private var global_var:String = "global_var";

private function getText():void
{
Alert.show("Level 1 : "+global_var+"\n\n"+this.ti.label);
var inner1:Function = function():void
{
Alert.show("Level 2 : "+global_var+"\n\n"+this.ti.label)
var inner2:Function = function():void
{
Alert.show("Level 3 : "+global_var+"\n\n"+this.ti.label);
}
inner2.call(this);
};
inner1.call(this);
}

]]>
/mx:Script>
/mx:Application>


Notice inner2.call(this) and inner1.call(this)? But how come the inner functions access global_var variable, any explanation? In the Adobe Documentation, programming_actionscript3.pdf, Under section "Understanding variable scope", these lines are specified :

/*******************************************************************************
ActionScript variables, unlike variables in C++ and Java, do not have block-level scope. A
block of code is any group of statements between an opening curly brace ( { ) and a closing
curly brace ( } ). In some programming languages, such as C++ and Java, variables declared
inside a block of code are not available outside that block of code. This restriction of scope is
called block-level scope, and does not exist in ActionScript. If you declare a variable inside a
block of code, that variable will be available not only in that block of code, but also in any
other parts of the function to which the code block belongs.
*******************************************************************************/

The above answers our question, but the specification talks nothing about variable scopes. Its a relief to know there is a neat solution for the nested functions problem.

Thursday, February 21, 2008

Anonymous "functions" in Flex

I will not start this post with an introduction to what an anonymous function is. I assume most of you already know it. So, i was very happy with the notion of Function being a type in action script. That means i can define a function type and create multiple copies of it, probably not that useful. But i can pass around functions to other functions, treat them as values and perform operations on functions, i can combine functions in a way we write mathematic functions on paper, probably not exactly like that, because actionscript does not support operator overloading. Forget operator loading, actionscript does not support function overloading, it also does not allow a constructor to be private. What is wierd is that, private constructors were supported untill actionscript 2, but discarded in actionscript 3.

So as an example, consider this

function action(condition:Fucntion, how:Function, preProcess:Function, postProcess:Function)
{
while(condition())
{
preProcess();
how();
postProcess();
}
}

It is not important how we implement this, the important point is the concept of abstracting the operations/functions and creating reusable functions, and avoid code duplication. There are many more advantages of treating functions as values, a similar concept in C++ is a function object or a functor, but those uses and advantages in a later blog.

So, actionscript provides a function type, and also supports anonymous functions which is great, BUT BUT, the anonymous functions are screwed up, their scopes are not at all consistent. When you refer to the variable "this" in a anonymous function, the result is not similar when you refer "this" in a function defined by name. so we cannot do this,

remoteObj.send(args,
function(event:ResultEvent):void
{
PopupManager.closePopup(this);
}
, fault_handler_function);

The above results in a runtime error. So we have to do this

remoteObj.send(args, result_handler, fault_handler_function);

private function result_handler(event:ResultEvent):void
{
PopupManager.removePopup(this);
}


Why this inconsistency, and why isnt this specified anywhere in the documentation. Is there a actionscript specification these people are working on? Is it avilable anywhere on the internet?

An update to this subject, the solution is posted here.

I did a quick search and i found the specification for actionscript 3. http://livedocs.adobe.com/specs/actionscript/3/wwhelp/wwhimpl/js/html/wwhelp.htm. Is this supposed to be the specification for a language, well, it doesnt at all look like it and it is a total waste. It looks like just an another tutorial.

Thursday, February 07, 2008

MySql - Permissions

I spent a lot of time reading the official documentation and a lot of tutorials and blogs, but didnt find what i wanted, untill i found this article. The information is to the point and does not miss a single point.

Ian Gliffin is the man who wrote this, and he has a lot of articles on Mysql.

Friday, February 01, 2008

Code Generation - Good or Bad?

I am planning to put my thoughts about this subject on my blog. But wanted to know what people think about this in the meantime.

Please leave comments.