On Friday, Jul 25, 2003, at 02:18 US/Pacific, Tim Blair wrote:
Check out the second section in the cfm file -- you can grab a reference
directly to a method within a CFC and then use that method outside the
CFC. I tried it using the getinstancevars() method but got a "Variable
INSTANCE is undefined" error, so obviously this is being used outside
the scope of the CFC.


Is this correct (and expected) behaviour?

Yes. I believe CF5 allowed you assign a UDF to a variable and pass it around:


<cfscript>
function foo() { return 42; }
bar = foo;
x = bar();
</cfscript>

(It's certainly legal in CFMX)

A function is actually compiled to a class and then instantiated so functions and methods can be passed around just like any other object. As you also discovered, when you execute the function, it *dynamically* looks up variables. This allows you to do things like this:

<!--- thing.cfc --->
<cfcomponent>
        <cfset instance = structNew() />
        <cffunction name="setFoo" returntype="thing">
                <cfargument name="x">
                <cfset instance.x = arguments.x />
                <cfreturn this />
        </cffunction>
        <cffunction name="getFoo" returntype="any" />
                <cfreturn instance.x />
        </cffunction>
</cfcomponent>

<!--- naughty.cfm --->
<cfscript>
function hijacker() {
        return instance;
}
thingie = createObject("component","thing");
thingie.naughty = hijacker;
stolenData = thingie.naughty();
</cfscript>

Two things to note:
a) you can create a UDF that references an (as yet) undeclared variable
b) you can insert new methods into object instances (and call them)

This is a direct consequence of functions being 'objects' and the 'hijacking' of variables is a direct consequence of ColdFusion having 'dynamic binding' for variables. CF would have to be a more complex language to disallow that (it would have to introduce 'closures' - tentative binding of variables).

Note that being able to pass functions around can be very useful. Consider this example:

<cfscript>
function transform(anArray,aFunction) {
        for (i = 1; i le arrayLen(anArray); i = i + 1) {
                anArray[i] = aFunction(anArray[i]);
        }
        return anArray;
}
function twice(x) {
        return x + x;
}
function thrice(x) {
        return x * 3;
}
a = arrayNew(1);
a[1] = 1;
a[2] = 2;
b = transform(a,twice);
c = transform(a,thrice);
</cfscript>
<cfdump label="a doubled" var="#b#" />
<cfdump label="a trebled" var="#c#" />

Being able to parameterize behavior like is very powerful.

Sean A Corfield -- http://www.corfield.org/blog/

"If you're not annoying somebody, you're not really alive."
-- Margaret Atwood

----------------------------------------------------------
You are subscribed to cfcdev. To unsubscribe, send an email
to [EMAIL PROTECTED] with the word 'unsubscribe cfcdev' in the message of the email.


CFCDev is run by CFCZone (www.cfczone.org) and supported
by Mindtool, Corporation (www.mindtool.com).

Reply via email to