Working with user-defined functions (UDFs)

This article is designed only to be an introduction to user-defined functions. If you have never used them before, it should provide enough information to get you going.

A brief history of functions

User-defined functions or UDFs are a nice way of encapsulating certain types of functionality. They are like a black box where you feed in certain values and receive a single result. Once the function is written, how it works no longer matters. All you need think about is what data to feed the function. This encapsulation of functionality makes it easy to share functions with others or to use functions others have created. There is now a substantial library at CFLib.org where you can find hundreds of functions already written and tested.

When UDFs were introduced in ColdFusion 5, it was necessary to use ColdFusion script (wrapped in cfscript tags). CF script is similar to tag-based CFML markup but covering only a small subset of functionality. Many developers prefer it for computationally intensive work as they find it easier to read.

With CFMX and the addition of the cffunction tag, you can now write functions using either script or tag-based markup. Of course, with tag-based markup available, you are no longer limited in what your functions can do.

Here's a very simple function that counts the number of words in a string. This is not a very exciting UDF, but it's a good place to start:

<cfscript>
  function wordCount(str) {
    var count = listLen(str, " #chr(9)##chr(10)##chr(11)##chr(12)##chr(13)#");
    return count;
  }
</cfscript>

Here it is again using tag-based markup. As you can see, it is considerably more verbose. This version will only work on or later:

<cffunction 
  name="wordCount" 
  returntype="numeric" 
  output="no"
>
  <cfargument
    name="str" 
    type="string" 
    required="yes"
  >
	
  <cfset var count = listLen(str, " #chr(9)##chr(10)##chr(11)##chr(12)##chr(13)#")>
  <cfreturn count>
	
</cffunction>

And here's how we might use this (both versions will work the same way):

<p>
  Number of words in this article: 
  <cfoutput>#wordCount(article)#</cfoutput>.
</p>

OK so how would I go about using this "word count" UDF on my site?

Well, I'm glad you asked! You could simply include the code in the page where you want to use it, then call it as described above. In fact, this is a good way to check that the is working properly.

However, one of the key ideas behind UDFs is reusability. So it's a good idea to store your UDFs in a library that you can include whenever you like. A library is really just a .cfm file containing a bunch of function definitions. You might like to create several different libraries for different types of function: localization.cfm, stringlib.cfm, mathlib.cfm. When you want to use a function, simply cfinclude the appropriate library.

If you prefer, you can simply include your library in your root Application.cfm file. In this way, your functions are available everywhere throughout your app, just like built-in functions! Well, almost everywhere.

Almost? Well, when you declare a function it is placed in the variables scope. Inside a custom tag, a new variables scope is created that is different from the variables scope of the calling page. So your functions won't be available inside custom tags (or any file called with the cfmodule tag.

If you never run into this problem then don't worry about it. If you do, here are your options:

  1. Either include the library again from within your custom tag; or
  2. shift your UDFs into a scope that remains visible inside custom tags.

If you want to try option 2, I recommend the request scope. It is visible to any code that is part of the current page request, but it is not stored from request to request. You could try a persistent scope such as application, session, or server but these are harder to work with and debug.

Shift your into the request scope like this:

<cfscript>
  function wordCount(str) {
    var count = listLen(str, " ,#chr(9)#,#chr(10#,#chr(#11)#,#chr(#12)#,#chr(#13)#");
    return count;
  }
  request.wordCount = wordCount;
</cfscript>

That's right — it's just one extra line of code!

Where to from here?

Try downloading some UDFs from the large library at CFLib.org or from the smaller ESWsoftware library. Soon you'll be managing libraries of functions. If you want to shift an entire library of UDFs into the request scope, use this custom tag.

4 May 2004

User-Defined Functions. UDFs were added to ColdFusion 5 and are usually written using CFScript, but, with the release of ColdFusion MX, may also be written with regular CFML tag-based markup.
User-Defined Function. UDFs were added to ColdFusion 5 and are usually written using CFScript, but, with the release of ColdFusion MX, may also be written with regular CFML tag-based markup.
ColdFusion Markup Language: Tag-based language processed by a ColdFusion web application server
Macromedia ColdFusion MX
ColdFusion web application server version 6 or later.