An argument's name should represent its use. For example, the following code is unlikely to result in confusion:
<cfscript> function SumN(Addend1,Addend2) { return Addend1 + Addend2; } </cfscript> <cfset x = 10> <cfset y = 12> <cfoutput>#SumN(x,y)#</cfoutput>
The following, similar code is more likely to result in programming errors:
<cfscript> function SumN(x,y) { return x + y; } </cfscript> <cfset x = 10> <cfset y = 12> <cfoutput>#SumN(x,y)#<cfoutput>
ColdFusion passes the following data types to the function by value:
As a result, any changes that you make in the function to these arguments do not affect the variable that was used to call the function, even if the calling code is on the same ColdFusion page as the function definition.
ColdFusion passes queries, structures, and external objects such as COM objects into the function by reference. As a result, any changes to these arguments in the function also change the value of the variable in the calling code.
For an example of the effects of passing arguments, see Passing complex data.
Structures, queries, and complex objects such as COM objects are passed to UDFs by reference, so the function uses the same copy of the data as the caller. Arrays are passed to user-defined functions by value, so the function gets a new copy of the array data and the array in the calling page is unchanged by the function. As a result, you must handle arrays differently from all other complex data types.
Passing structures, queries, and objects
For your function to modify the caller's copy of a structure, query, or object, you must pass the variable as an argument. Because the function gets a reference to the caller's structure, the caller variable reflects all changes in the function. You do not have to return the structure to the caller. After the function returns, the calling page accesses the changed data by using the structure variable that it passed to the function.
If you do not want a function to modify the caller's copy of a structure, query, or object, use the Duplicate function to make a copy and pass the copy to the function.
If you want your function to modify the caller's copy of the array, the simplest solution is to pass the array to the function and return the changed array to the caller in the function return statement. In the caller, use the same variable name in the function argument and return variable.
The following example shows how to directly pass and return arrays. In this example, the doubleOneDArray function doubles the value of each element in a one-dimensional array.
<cfscript> //Initialize some variables //This creates a simple array. a=ArrayNew(1); a[1]=2; a[2]=22; //Define the function. function doubleOneDArray(OneDArray) { var i = 0; for ( i = 1; i LE arrayLen(OneDArray); i = i + 1) { OneDArray[i] = OneDArray[i] * 2; } return OneDArray; } //Call the function. a = doubleOneDArray(a); </cfscript> <cfdump var="#a#">
This solution is simple, but it is not always optimal:
If you do not use the return statement to return the array to the caller, you can pass the array as an element in a structure and change the array values inside the structure. Then the calling page can access the changed data by using the structure variable it passed to the UDF.
The following code shows how to rewrite the previous example using an array in a structure. It returns True as a status indicator to the calling page and uses the structure to pass the array data back to the calling page.
<cfscript> //Initialize some variables. //This creates an simple array as an element in a structure. arrayStruct=StructNew(); arrayStruct.Array=ArrayNew(1); arrayStruct.Array[1]=2; arrayStruct.Array[2]=22; //Define the function. function doubleOneDArrayS(OneDArrayStruct) { var i = 0; for ( i = 1; i LE arrayLen(OneDArrayStruct.Array); i = i + 1) { OneDArrayStruct.Array[i] = OneDArrayStruct.Array[i] * 2; } return True; } //Call the function. Status = doubleOneDArrayS(arrayStruct); WriteOutput("Status: " & Status); </cfscript> </br> <cfdump var="#arrayStruct#">
You must use the same structure element name for the array (in this case Array) in the calling page and the function.
All function arguments exist in their own scope, the Arguments scope.
The Arguments scope exists for the life of a function call. When the function returns, the scope and its variables are destroyed.
However, destroying the Argument scope does not destroy variables, such as structures or query objects, that ColdFusion passes to the function by reference. The variables on the calling page that you use as function arguments continue to exist; if the function changes the argument value, the variable in the calling page reflects the changed value.
The Arguments scope is special, in that you can treat the scope as either an array or a structure. This dual nature of the Arguments scope is useful because it makes it easy to use arguments in any of the following circumstances:
The following sections describe the general rules for using the Arguments scope as an array and a structure. For more information on using the Arguments scope in functions defined using CFScript, see Using the Arguments scope in CFScript. For more information on using the Arguments scope in functions defined using the cffunction tag, see Using the Arguments scope in cffunction definitions.
The contents of the Arguments scope
The following rules apply to the Arguments scope and its contents:
When you call a function that you defined using CFScript, you must pass the function a value for each argument declared in the function definition. Therefore, the Arguments scope for a CFScript call does not have empty slots.
The following example shows these rules. Assume that you have a function declared, as follows:
<cffunction name="TestFunction"> <cfargument name="Arg1"> <cfargument name="Arg2"> </cffunction>
You can call this function with a single argument, as in the following line:
<cfset TestFunction(1)>
The resulting Arguments scope looks like the following:
As an array |
As a structure |
||
---|---|---|---|
Entry |
Value |
Entry |
Value |
1 |
1 |
Arg1 |
1 |
2 |
undefined |
Arg2 |
undefined |
In this example, the following functions return the value 2 because there are two defined arguments:
ArrayLen(Arguments) StructCount(Arguments)
However, the following tests return the value false, because the contents of the second element in the Arguments scope is undefined.
Isdefined("Arguments.Arg2") testArg2 = Arguments[2]> Isdefined("testArg2")
Using the Arguments scope as an array
The following rules apply to referencing Arguments scope as an array:
However, using argument names in this manner is not good programming practice because you cannot ensure that you always use the same optional argument names when calling the function.
To demonstrate these rules, define a simple function that displays the contents of its Arguments array and call the function with various argument combinations, as the following example shows:
<cffunction name="TestFunction" > <cfargument name="Arg1"> <cfargument name="Arg2"> <cfloop index="i" from="1" to="#ArrayLen(Arguments)#"> <cfoutput>Argument #i#: #Arguments[i]#<br></cfoutput> </cfloop> </cffunction> <strong>One Unnamed argument</strong><br> <cfset TestFunction(1)> <strong>Two Unnamed arguments</strong><br> <cfset TestFunction(1, 2)> <strong>Three Unnamed arguments</strong><br> <cfset TestFunction(1, 2, 3)> <strong>Arg1:</strong><br> <cfset TestFunction(Arg1=8)> <strong>Arg2:</strong><br> <cfset TestFunction(Arg2=9)> <strong>Arg1=8, Arg2=9:</strong><br> <cfset TestFunction(Arg1=8, Arg2=9)> <strong>Arg2=6, Arg1=7</strong><br> <cfset TestFunction(Arg2=6, Arg1=7)> <strong>Arg1=8, Arg2=9, Arg3=10:</strong><br> <cfset TestFunction(Arg1=8, Arg2=9, Arg3=10)> <strong>Arg2=6, Arg3=99, Arg1=7</strong><br> <cfset TestFunction(Arg2=6, Arg3=99, Arg1=7)>
Using the Arguments scope as a structure
The following rule applies when referencing Arguments scope as a structure:
The following rules are also true, but avoid writing code that uses them. To ensure program clarity, only use the Arguments structure for arguments that you name in the function definition. Use the Arguments scope as an array for optional arguments that you do not declare in the function definition.
Using the Arguments scope in CFScript
A function can have optional arguments that you do not have to specify when you call the function. To determine the number of arguments passed to the function, use the following function:
ArrayLen(Arguments)
When you define a function using CFScript, the function must use the Arguments scope to retrieve the optional arguments. For example, the following SumN function adds two or more numbers together. It requires two arguments and supports any number of additional optional arguments. You can refer to the first two, required, arguments as Arg1 and Arg2 or as Arguments[1] and Arguments[2]. You must refer to the third, fourth, and any additional optional arguments as Arguments[3], Arguments[4], and so on.
function SumN(Arg1,Arg2) { var arg_count = ArrayLen(Arguments); var sum = 0; var i = 0; for( i = 1 ; i LTE arg_count; i = i + 1 ) { sum = sum + Arguments[i]; } return sum; }
With this function, any of the following function calls are valid:
SumN(Value1, Value2) SumN(Value1, Value2, Value3) SumN(Value1, Value2, Value3, Value4)
and so on.
The code never uses the Arg1 and Arg2 argument variables directly, because their values are always the first two elements in the Arguments array and it is simpler to step through the array. Specifying Arg1 and Arg2 in the function definition ensures that ColdFusion generates an error if you pass the function one or no arguments.
For more information on the Arguments scope, see About the Arguments scope.
Using the Arguments scope in cffunction definitions
When you define a function using the cffunction tag, you generally refer to the arguments directly by name if all arguments are named in the cfargument tags. If you do use the Arguments scope identifier, follow the rules listed in About the Arguments scope.