Executing A Recursive CFThread In ColdFusion 9

Posted February 23, 2010 at 9:50 AM by Ben Nadel

Tags: ColdFusion

Earlier this morning, I explored the fact that ColdFusion CFThread tag bodies are executed as function calls. While I didn't see any practical value to knowing this (yet), it did present a few more opportunities for exploration. Any time there is a function, there is an opportunity to play with one of computer science's greatest achievements: recursion. Given that the underlying mechanism of the CFThread tag is a function, I wondered if I could use it to execute CFThread recursively.

Before I show you this code, please note that this exploration is completely for fun! I am in no way advocating that using this approach has any benefits over using a standard ColdFusion function; in fact, this approach is markedly more complicated. That said, as a basic recursive experiment, I tried to have CFThread compute a mathematical factorial:

  • <!--- Launch a thread that will act as factorial calculation. --->
  • <cfthread
  • name="factorial"
  • value="10">
  •  
  • <!---
  • NOTE: In the following code, we can keep referring to
  • attributes since it is always being passed as a method
  • argument.
  • --->
  •  
  • <!---
  • Check to see if the value is 10. If so, then we want to
  • store the result into the thread. Only
  • --->
  • <cfif (attributes.value eq 10)>
  •  
  • <!--- Get the next factorial result. --->
  • <cfinvoke
  • returnvariable="result"
  • method="#getFunctionCalledName()#"
  • attributes="#{ value = (attributes.value - 1) }#"
  • />
  •  
  • <!---
  • Multiple the previous factorial with the current value
  • and store it into the Thread object.
  • --->
  • <cfset thread.result = (attributes.value * result) />
  •  
  • <!--- Check to see if the value is greater than one. --->
  • <cfelseif (attributes.value gt 1)>
  •  
  • <!--- Get the next factorial. --->
  • <cfinvoke
  • returnvariable="result"
  • method="#getFunctionCalledName()#"
  • attributes="#{ value = (attributes.value - 1) }#"
  • />
  •  
  • <!---
  • Return the current value multiplied by the next
  • recursive value.
  • --->
  • <cfreturn (attributes.value * result) />
  •  
  • <cfelse>
  •  
  • <!---
  • If we are at one, simply return the value - there is
  • no further recursion that we can apply.
  • --->
  • <cfreturn 1 />
  •  
  • </cfif>
  •  
  • </cfthread>
  •  
  •  
  • <!---
  • Join the thread to make sure that we can get at the
  • thread variables.
  • --->
  • <cfthread action="join" />
  •  
  •  
  • <!--- Output the results. --->
  • <cfoutput>
  •  
  • 10! = #cfthread.factorial.result#
  •  
  • </cfoutput>

As you can see, I am using ColdFusion 9's new function, getFunctionCalledName(), to figure out the name of the function object behind the CFThread tag. Then, using that method name, I am able to invoke the CFThread tag body programmatically with CFInvoke. When I call the method recursively, I have to be careful to set up the appropriate environment, passing in an Attributes struct as an argument each time. When we run the above code, we get the following output:

10! = 3628800

As you can see, the CFThread tag was able to execute recursively, working its way down to one (1) and then back up, multiplying each value to find the given factorial.

Again, there is nothing practical about this - it was just a fun experiment (depending on what your definition of "fun" is).




Reader Comments

Feb 23, 2010 at 10:01 AM // reply »
18 Comments

Great post Ben.

Although there may not be any necessity for such functions (yet, anyway.. you may have stumbled across a life-changing bit of code here ;) ) the fact remains that once again you've taken the time to explore and delve further into the code and it's underlying assets, always asking "what if?" or "why?" compared to the question generally asked which is "how?".

Awesome.


Feb 23, 2010 at 10:07 AM // reply »
10,638 Comments

@Matt,

Thanks my man - I'm glad you appreciate the extra digging I try to do. I think there is something fun knowing that the function is executing recursively in *parallel* to the page. Of course, there's nothing that would stop someone from simply passing in another function reference to the CFThread tag and executing in parallel that way... but, this was fun :)


Feb 24, 2010 at 1:35 PM // reply »
132 Comments

This the coolest use of getFunctionCalledName() I've seen. There was some initial feedback on the prerelease like "what would you ever use that for!" and no one even dreamed of anything like this.


Feb 24, 2010 at 2:10 PM // reply »
10,638 Comments

@Elliott,

Thanks you my good man :)


Post A Comment

Comment Etiquette: Please do not post spam. Please keep the comments on-topic. Please do not post unrelated questions or large chunks of code. And, above all, please be nice to each other - we're trying to have a good conversation here.

Please review the following issues:

Author Name:


Author Email:

Author Website:

Comment:

Supported HTML tags for formatting: <strong>bold</strong>   <em>italic</em>   <code>code</code>







  • Help Wanted - Find Your Next ColdFusion Job
InVision App - Prototyping Made Beautiful With Prototyping Tools Ben Nadel's Company - Epicenter Consulting Recent Blog Comments
Feb 3, 2012 at 10:49 PM
How I Got Node.js Running On A Linux Micro Instance Using Amazon EC2
Wow this was really helpful! Only thing I would add is you need to update your .bash_profile after you edit the secure_path. This is what I did: $ . ~/.bash_profile Otherwise, NPM won't be found. ... read »
Feb 3, 2012 at 10:14 PM
Pushing Base64-Encoded Images Over HTML5 WebSockets With Pusher And ColdFusion
@Ben, Just wanted to let you know that pusher are soon to start limiting sizes on messages. This was the detail that came through in the Feb dispatch: "However, we will soon be limiting the s ... read »
Feb 3, 2012 at 5:05 PM
Regular Expressions Make CSV Parsing In ColdFusion So Much Easier (And Faster)
I tried using your RegEx in my C# program, but it was matching an extra empty-string at the end and so I would end up with an extra field that doesn't exist, so I changed it to this: (^|,)("(?: ... read »
Feb 3, 2012 at 3:47 PM
ColdFusion Supports HTTP Verbs PUT And DELETE (As Well As GET And POST)
Josh Cyr posted this on Twitter just a little bit ago. Thought it was appropriate. http://stackoverflow.com/questions/1619152/how-to-create-rest-urls-without-verbs/1619677#1619677 ... read »
Feb 3, 2012 at 2:28 PM
Changing The Execution Context Of Your Self-Executing Function Blocks In JavaScript
@Michael, You definitely make a good point (and extra points for quoting movies - I love movies). When you use a return() statement to define the object's public API, it does provide a consistent a ... read »
Feb 3, 2012 at 2:04 PM
Changing The Execution Context Of Your Self-Executing Function Blocks In JavaScript
To quote Jurassic Park: "Just because you can doesn't mean you should". I completely, utterly disagree with the thought that this is more readable. Consider the current module pattern: if ... read »
Feb 3, 2012 at 1:10 PM
REST API Design Rulebook By Mark Masse
@Jordan, Yeah, WRML was created by Mark Masse (author of the book). I also found it to be a bit convoluted. I suppose it is intended to allow the Client to be able to programmaticaly respond to cha ... read »
Feb 3, 2012 at 1:08 PM
ColdFusion Supports HTTP Verbs PUT And DELETE (As Well As GET And POST)
@Jason, To be honest, I don't have good answers for that kinds of stuff. And, to the point, that is specifically why I *really* liked the REST API Design Rulebook by Mark Masse - he just cuts throu ... read »