<!--- container.cfc --->
<cfcomponent>
<cfscript>
variables._arr = arrayNew(1);
variables._curIndex = 0;
// adds an element to the container
function add(value)
{
_curIndex = _curIndex + 1;
_arr[_curIndex]=value;
}
// iterates over the container, letting a closure
// specify what to do at each iteration
function each(closure)
{
for (i=1; i lte _curIndex; i=i+1)
{
closure.call(_arr[i]);
}
}
</cfscript>
</cfcomponent>
Compare his each() method to mine. He names the method and then repeatedly binds the value variable. That doesn't actually do what he thinks. If you want to call a closure, you simply call it with arguments as shown above.
However, in order to do that, you need to identify the arguments when you create the closure. You do that by specifying the argument names in the call to new() like this:
<cfcomponent>
<cfscript>
variables._arr = arrayNew(1);
variables._curIndex = 0;
// adds an element to the container
function add(value)
{
_curIndex = _curIndex + 1;
_arr[_curIndex]=value;
}
// iterates over the container, letting a closure
// specify what to do at each iteration
function each(closure)
{
for (i=1; i lte _curIndex; i=i+1)
{
closure.call(_arr[i]);
}
}
</cfscript>
</cfcomponent>
cf.new("<cfset value = value + 3>" &
"<cfoutput>##value##</cfoutput>" &
"<cfset beenhere = true>","value")
That fixes part of his problem.
His other problem is the beenhere variable. He wants to bind that variable to the context in which the closure is created. Note that he wants to update the variable inside the closure and output its (updated) value outside the closure. In order to do that, you need to bind the context. First we change the closure to this:
"<cfoutput>##value##</cfoutput>" &
"<cfset beenhere = true>","value")
cf.new("<cfset value = value + 3>" &
"<cfoutput>##value##</cfoutput>" &
"<cfset outer.beenhere = true>","value")
We've made beenhere a member of a structure. Now we can bind the variables context of the closure_test.cfm page to that structure:
"<cfoutput>##value##</cfoutput>" &
"<cfset outer.beenhere = true>","value")
cf.new("<cfset value = value + 3>" &
"<cfoutput>##value##</cfoutput>" &
"<cfset outer.beenhere = true>","value")
.bind(outer=variables)
This causes the (free) reference to outer in the closure to be bound to the (creation-time) variables scope context.
Here's the updated test page:
"<cfoutput>##value##</cfoutput>" &
"<cfset outer.beenhere = true>","value")
.bind(outer=variables)
<!--- closure_test.cfm --->
<cfscript>
cf = createObject("component","org.corfield.closure.ClosureFactory");
container = createObject("component","container");
container.add(10);
container.add(20);
container.add(30);
beenhere = false;
c = cf.new("<cfset value = value + 3>" &
"<cfoutput>##value##</cfoutput>" &
"<cfset outer.beenhere = true>","value")
.bind(outer=variables);
container.each(c);
c = cf.new("<br/><cfoutput>This container has the value ##value## in it</cfoutput>","value");
container.each(c);
</cfscript>
<cfoutput>
#beenhere# <!--- outputs false --->
</cfoutput>
Hope that helps anyone else who is trying to use my Closures library!<cfscript>
cf = createObject("component","org.corfield.closure.ClosureFactory");
container = createObject("component","container");
container.add(10);
container.add(20);
container.add(30);
beenhere = false;
c = cf.new("<cfset value = value + 3>" &
"<cfoutput>##value##</cfoutput>" &
"<cfset outer.beenhere = true>","value")
.bind(outer=variables);
container.each(c);
c = cf.new("<br/><cfoutput>This container has the value ##value## in it</cfoutput>","value");
container.each(c);
</cfscript>
<cfoutput>
#beenhere# <!--- outputs false --->
</cfoutput>
0 responses