G'day:
I'm just soliciting opinions about a potential feature request here. I'd like to be able to force CFML to pass arguments / parameters by reference rather than by value.
I wrote an article a while ago about "
Complex data-types in CF, and how they're not copied by reference" which could be a reasonable primer if you're not already comfortable with the notion of references and how they work (or aren't used when they should be) in CFML.
In ColdFusion (but not in Railo) for some reason, arrays are always duplicated when they are passed as function arguments or tag parameters (incl. custom tag attributes); whereas data of other complex types are passed by reference (for all intents and purposes). Here's some quick code to demonstrate:
function arrayHandler(array){
arrayAppend(arguments.array, "toru");
writeDump(var={variablesScope=variables.array, argumentsScope=arguments.array}, label="Within arrayHandler()");
}
function structHandler(struct){
struct.six = "ono";
writeDump(var={variablesScope=variables.struct, argumentsScope=arguments.struct}, label="Within structHandler()");
}
array = ["tahi", "rua"];
struct = {four="wha", five="rima"};
writeDump(var=[array,struct], label="Before function calls");
writeOutput("<hr>");
arrayHandler(array);
writeOutput("<hr>");
structHandler(struct);
writeOutput("<hr>");
writeDump(var=[array,struct], label="After function calls");
On CF this outputs:
Before function calls - array |
1 |
Before function calls - array |
1 | tahi |
2 | rua |
|
2 |
Before function calls - struct |
FIVE | rima |
FOUR | wha |
|
Within arrayHandler() - struct |
ARGUMENTSSCOPE |
Within arrayHandler() - array |
1 | tahi |
2 | rua |
3 | toru |
|
VARIABLESSCOPE |
Within arrayHandler() - array |
1 | tahi |
2 | rua |
|
Within structHandler() - struct |
ARGUMENTSSCOPE |
Within structHandler() - struct |
FIVE | rima |
FOUR | wha |
SIX | ono |
|
VARIABLESSCOPE |
Within structHandler() - struct |
FIVE | rima |
FOUR | wha |
SIX | ono |
|
After function calls - array |
1 |
After function calls - array |
1 | tahi |
2 | rua |
|
2 |
After function calls - struct |
FIVE | rima |
FOUR | wha |
SIX | ono |
|
And on Railo, there is a key difference (I've trimmed the struct part out of this dump for the sake of brevity):
Within arrayHandler() |
Struct |
ARGUMENTSSCOPE |
|
VARIABLESSCOPE |
|
|
Notice how in ColdFusion the array in the function is not the same one as the array in the calling code: changes to the array in the function do not affect the calling code. Whereas in Railo they're the same arrays: changes to the array in the function also change the array in the calling code.
Right, so we're on the same page now.
I think ColdFusion is doing the wrong thing here, but I also think it's too late in the day to "fix" it.
What I'd like to be able to do instead is to have some sort of annotation to say "pass this thing as a reference", eg:
function arrayHandler(required &array array){
}
Where
&array signifies and array reference, rather than the array itself.
Initially it might seem like this is limited to only arrays, but I also see it as being useful for functions which manipulate & "return" strings as well. Strings are passed by value, and strings can get rather large. So it would be useful to also be able to pass strings by reference too, I think.
Also when using threads, for reasons best know to itself, ColdFusion passes
everything into a thread by value:
struct = {one="tahi", two="rua"};
thread name="t1" struct=struct {
struct.three = "toru";
}
thread action="join" name="t1";
writeDump(struct);
Yields:
Railo is again more sensible here:
I'd like to make CF be sensible here too.
This would not be functionality that would get use every day (well: for arrays it would, for me, I guess), and is not groundbreaking, but would be useful I think?
Thoughts?
I've raised a ticket for this:
3638235.
--
Adam