This didn't quite make the docs, nor do I think it was mentioned at CFUNITED, but one of the more interesting functions added to ColdFusion 9 is getFunctionCalledName. This returns the name of the calling function. Here is a somewhat useless example:
<cfscript>
function foobar() {
return getFunctionCalledName();
}
</cfscript>
<cfoutput>#foobar()#</cfoutput>
This returns foobar, since the result of getFunctionCalledName is the name of the currently executing method. A slightly more sensible example, created by Elliott Sprehn, is the following:
component {
variables.x = 1;
variables.y = 2;
function init() {
return this;
}
function get() {
var name = getFunctionCalledName();
return variables[mid(name,4,len(name))];
}
function set(value) {
var name = getFunctionCalledName();
variables[mid(name,4,len(name))] = value;
}
this.getX = get;
this.getY = get;
this.setX = set;
this.setY = set;
}
Notice a few things in play here. He created one generic get and set function and then made copies of them for getX/getY and setX/setY. The generic functions work by using the getFunctionCalledName to figure out the real name of the function and update the appropriate value. As an example:
<cfset es = new es()>
<cfdump var="#es#">
<cfset es.setX("foo")>
<cfoutput>#es.getX()#</cfoutput>
So can folks think of any interesting uses for this?
Archived Comments
Very cool. I've been looking for this feature to use with bug alerts. Ideally I'd like to automatically specify which function and class or file in which an issue occurred. Does any one have any idea how to do this in CF8 (perhaps with java)?
This gets me thinking perhabs this could be used in
error handling. Where you would be able to see the precise function that through you the error. Hmmm might
have to code something here.
Whoah, it's like what we sometimes try to do with onMissingMethod(), but more elegant because we won't need one big if..then..else block for the different types of dynamic methods we want to implement.
Plus, the method names can still be dynamically generated, say, in the init() method! (I'm assuming this, haven't test it)
Interesting that they added this. I posted something similar to this back in February of last year http://www.garyrgilbert.com...
An Adobe forums user wanted to know how to find out what function called his function, or method. Back then with cf8 the only way was to force and catch an error to get the stack trace, and parse out the function name. A total hack, now I see they have provided a function to do that for you. Pretty cool.
Actually just read entire post again, first pass I misunderstood the function call.... so my post in february of last year is similar in that its totally different...
sigh I need another coffee so that I am really awake
From a design perspective, one could argue that this function should be used with caution, because it violates the so-called 'Hollywood principle' (don't call us, we will call you). Usually it is best when a method just does it's own thing, oblivious of the object and/or method that is calling it. Otherwise the behavior of the method might be dependent of some characteristics of the caller, causing tight coupling which may reduce maintainability; the method than has two potential reasons to change:
1) because it's own logic must be changed
2) because something changed in one or more callers
Ideally methods and/or object have only one potential reason for change.
Besides this caveat, this function allows for even more flexibility, which in my opinion is the number one advantage of CFML over other languages like Java. I wonder what people can come up with now that they know about this...
@Micah,
you can kind of do this in cf8, however it's extremely hackish. basically what you can do is create a java.lang.Execption and then parse out the information from the exceptions tagcontext. if you want to see it in the real world, have a look at the CFWheels source code for the $deprecated().
http://code.google.com/p/cf...
We're using this technique to announce deprecated elements of the framework to developers and giving them a heads up that these elements could be removed in a future release.
Interesting function. It would be cool if they could also provide a method to get the reference to the function object itself as well. I like your example with the generic getter/setters.
@Ben: That example was from Elliott Sprehn - super smart CF guy. :)
@Ray,
No doubt Elliott is wicked smart (too bad he wasn't at CFUNITED this year - I hear he had an internship at Microsoft). His example is cool, but breaks if the target method is not stored in the variables scope.
How would the method _not_ be stored in the variables scope?
If you store a pointer to it in the request scope or something. I am not talking about methods inside a CFC, but free-floating functions (which can be pulled out of a CFC as well).
Ah, interesting - now I get what you mean.
It originally came up because I wanted to be able write a UDF to the ram disk and then read it back in and have it be able to reference itself.
That's great! I needed this function for partial-mocking in cfSpec. When running a test, you can dynamically inject code to stub out methods on other objects so they are not actually called during the test. I've done it by pointing method names at onMissingMethod, but that's messy and only works when the function is called externally or with an explicit 'this' scope. Great news! Thanks for posting it.
I guess I should add this to my presentation for MAX. Thanks Ray for your post highlighting this function.
I'll probably use this in my views/templates.
We had a system setup where at the begging and end of functiosn we'd output a something like "Drawing start of table"...and then something similiar at the end the end. Of course the function only outputted when in debug mode.
At the end of the day you could throw a page into debug mode and easily find where in a template something was rendered. We tend to put lots of functions in our templates to better encapsulate them as they start to get really long.
This could help the developer find exactly what code is drawing a portion of the page. Hopefully it's return the CFC, CFM or whatever else might be useful.