Closures

Railo 4.0 now adds support for closures. Functions with a bang that you can use in your code

Closure support

Up until now, Railo has only supported regular Function Declarations. This means that you can use the tag <cffunction> in order to define a function which is then available in the local variables scope or the this scope of the component that it has been defined:

<cffunction name="myFunction">
<cfargument...>
</cffunction>

Railo 4.0 now allows you to define function expressions. This means that a function can be part of a larger expression and can have an assignment or not. These function expressions in Railo 4.0 must be anonymous.

The function expression in Railo can either be defined in a script context or even within a tag context. A function definition is considered a function expression when it is simultaneously defined and:

  • Assigned to a variable.
  • Passed into a function (as an argument).
  • Returned from a function.
  • Stored in a data structure (ie. array, struct, etc.).
  • Used in a control statement.

So, anytime you use the function keyword and not define a name, you are actually defining a function expression.

Another nice feature of Railo’s Closure support is that they can can be used within tags and not only cfscript for example:

<cfset clo=function (a){writeOutput(a);}>
<cf_test clo="#function (a){writeOutput(a);}#">

Now what’s the difference between a function expression and a closure?

They are not the same. A function expression can be used to define a function with the same functionality. A closure binds the variables inside the closure to the outer variables that exist inside the context where the closure is defined.

This binding will be done at definition time, which means that the variables from the surrounding context HAVE TO BE COPIED into the context of the closure. So while function expressions can be handled at compilation time, closures are more treated at compile time and evaluated accordingly.

Closures as arguments

A great addition is the value-binding aspect of closures, but even without these, passing in inline function declarations as arguments are a great benefit.

Before Railo 4.0 you always had to define a function (even if it was small) and use the defined function name as an argument for that function. Now you can define the function as an argument when you call the function in question.

There are a number of Railo 4.0 BIF’s (Built-in Functions) that take a function as an argument. This list is:

  • arrayEach( array, function )
  • arrayFilter( array, function )
  • arrayFind( array, function )
  • arrayFindAll( array, function )
  • arraySort( array, function )
  • listFilter( list, function )
  • structEach( struct, function )
  • structFilter( struct, function )
  • eachParallel(data, closure, numberOfThreads)?

Assigning Closures

A big problem which is not very obvious at first sight occurs when you define a closure and assign it to a variable. If the variable that you are assigning the closure to is a shared scope (server, application, session) you might end up wasting a lot of memory.

This is due to the fact that closures store their surrounding environment at definition time. So for instance this can be the complete variables scope. So if you assign a closure to a key in the application scope you might end up running out of memory in no time. So please be aware that it is very resource intense if you store closures in ANY shared scope.

AVOID THIS:

Application.myClosure = function() {
some code;
};