ColdFusion Zeus POTW - Extra edition again...

This post is more than 2 years old.

Hey, it's the holidays, so why not share one more quick ColdFusion Zeus update? This is another little feature that literally became available two days ago. If you've ever needed to dynamically invoke a CFC method, you know that's simply enough using cfinvoke. So for example:

<cfset s = new some()>

<cfset dynmeth = "test"> <cfinvoke component="#s#" method="#dynmeth#" returnVariable="res"> <cfdump var="#res#">

But of course, that's tag based. How do you do this in script? Unfortunately, the only way to do it was with evaluate, and while evaluate isn't as slow as it used to be, it can get messy to use.

ColdFusion Zeus corrects this by adding an invoke function.

<cfset s = new some()>

<cfset dynmeth = "test">

<cfset res = invoke(s, dynmeth)> <cfdump var="#res#">

The first argument is either an instance of a CFC or the name of a CFC. The second argument is the method to call. If you need to pass arguments, then you can simply add a third argument - a struct.

<cfset res = invoke(s, "sum", {x:4, y:9})> <cfoutput>#res#<p/></cfoutput>

By the way - take note of the fix to implicit struct notation. You can still use an equals sign ({x=4}), but colons work now too.

As a final quick aside - a certain person decided to take my words out of context regarding these Zeus previews I've been doing. That person also hasn't bothered to approve the comment I added 24 hours or so ago. I'm not going to bother linking to troll bait, but to be clear - these Zeus previews have intentionally focused on small things. It's easier for me to write, and secondly, it lets me ramp up slowly to the larger things we've announced already, like REST, closures, and web sockets. (Also, some of our larger features are still being hashed out.) For folks who attended my MAX preso, you already know this. Personally I'm really enjoying sharing these small, but useful, improvements, but I want folks to know that - obviously - we have bigger things in the works.

Raymond Camden's Picture

About Raymond Camden

Raymond is a senior developer evangelist for Adobe. He focuses on document services, JavaScript, and enterprise cat demos. If you like this article, please consider visiting my Amazon Wishlist or donating via PayPal to show your support. You can even buy me a coffee!

Lafayette, LA https://www.raymondcamden.com

Archived Comments

Comment 1 by Yuri Vorontsov posted on 12/22/2011 at 8:43 PM

Cool. But what's wrong with a good old

compObjStr = "com.whatever";
compObj = createObject("component" , compObjStr );

Gr
Yuri

Comment 2 by Raymond Camden posted on 12/22/2011 at 8:45 PM

I think you misunderstood. This isn't about creating a dynamic CFC. It is about calling a dynamic method on a CFC.

Comment 3 by Yuri Vorontsov posted on 12/22/2011 at 8:54 PM

Indeed!

Comment 4 by Joshua Miller posted on 12/22/2011 at 9:31 PM

Love the new features coming to CFScript - can't wait for every single tag to have a script equivalent. I for one love the little "teaser" features being announced - many of them are as important to me as the major additions. Closures are cool, but the hidden gem of functional implicit struct (and hopefully array) notation excites me more.

Comment 5 by Phillip Senn posted on 12/22/2011 at 10:21 PM

It took me a very long time to realize that in JavaScript, {x:4, y:9} was a way of passing an object with 2 name/value pairs. After all, there's no equal sign, so "how are these values getting set?" And assigning a value to a variable should be what you learn on day 1.

Comment 6 by Raymond Camden posted on 12/22/2011 at 10:23 PM

I'm just happy they added this - I do so much JS work now that I keep screwing up the assignments going back and forth.

Comment 7 by existdissolve posted on 12/22/2011 at 10:31 PM

Hi Ray---

As always, thanks for sharing about even the small enhancements coming in Zeus. I know the troll criticized the highlighting of these features, but for those of us who _actually_ like ColdFusion, this stuff is simply gold.

I look at it like this. I'm sure there are dozens and dozens of people who are waiting for X or Y *huge* feature to be implemented into CF. And I'm sure once X or Y is implemented, they will immediately use it to its full capability.

However, there are also a ton of us who use CF, will upgrade to Zeus when it's available, and will probably never use X or Y huge feature. But we will use the heck out of the fix for colons in implicit struct creation. We will use the new callstack capability. And we will use datetimeformat.

While all of these are certainly "small" in the grand scheme of all that CF does, can do, and will do, they also quickly add up for developers who use CF every day in the calculus of why we love using it, and why we anticipate what's to come in future versions.

Keep 'em coming!!

Comment 8 by Raymond Camden posted on 12/22/2011 at 10:38 PM

Thanks- much appreciated. :) There's still a lot more to show, and more nuggets like this (oh, like a new regular expression thing that I'll be coy about).

Comment 9 by Zach Stevenson posted on 12/22/2011 at 10:40 PM

This is very exciting, but I now have a ton of questions.
Can the new Invoke Method take a string as it's first value like how cfinvoke can take the name of a component for the component attribute? ex: invoke(component = "myComponent", method = "foo", arguments = {foo:'bar'});

If so, is this really the best thing to do? On each invoke it would be instantiating a temporary transient object that represents the string you passed in just so it can call the function on that object. The only use cases of passing a string that represents the object instead of the object itself would be utility components to fake static function calls. So wouldn't it make more sense to include the static modifier to components so you wouldn't even have to instantiate the object and have that overhead each time you called an invoke? Or further, wouldn't it make sense to add the ClassName.staticFunction() OR local.class = new ClassName; local.class.staticFunction() syntax to CF?

If not so, why is Invoke going to be a global function if the first argument is always a component? Wouldn't it make sense to make it a method on the component object? ex: myComponent.invoke(method = "foo", arguments = {foo:'bar'});

Comment 10 by Raymond Camden posted on 12/22/2011 at 10:45 PM

"Can the new Invoke Method take a string as it's first value like how cfinvoke can take the name of a component for the component attribute?"

Yes, I said that. :) "The first argument is either an instance of a CFC or the name of a CFC."

"If so, is this really the best thing to do?"
It depends. Almost always folks make an instance of a CFC and keep it around. But not always. Point is - both is supported.

"If not so, why is Invoke going to be a global function if the first argument is always a component?"

If I had to guess, to ensure it wouldn't break with folks who used invoke as a method name.

Comment 11 by Zach Stevenson posted on 12/22/2011 at 10:49 PM

Oops! I didn't even see the paragraph between the second and third examples.

"If I had to guess, to ensure it wouldn't break with folks who used invoke as a method name."
Good point.

Comment 12 by Zach Stevenson posted on 12/22/2011 at 11:00 PM

Love the JSON struct notation. That's definitely going to save me tons of time.

Comment 13 by Peter Boughton posted on 12/22/2011 at 11:23 PM

Is this invoke function instead of fixing obj[method](args) syntax? :/

Comment 14 by Raymond Camden posted on 12/22/2011 at 11:25 PM

Zach - to be clear - and you may know this - you can use implicit notation now - just not with colons. You know this, right? (And again - sorry if so. )

Peter - yes. :)

Comment 15 by Zach Stevenson posted on 12/22/2011 at 11:28 PM

Yes, I know you can, but that 2 second pause remembering which way you have to do it for the language you are currently in is 2 seconds you can never get back.

Comment 16 by Raymond Camden posted on 12/22/2011 at 11:32 PM

Heh good point there. ;)

Comment 17 by Gary F posted on 12/23/2011 at 3:15 AM

I like the slow reveals you're blogging, Ray. Little tantalising morsels of entertainment building up to a crescendo with an explosion of the headline features! Hmm, a bit like sex which would be a disappointment if you did what I just described in reverse! Can I say that?

Comment 18 by Raymond Camden posted on 12/23/2011 at 3:17 AM

You said it - too late now. ;)

Comment 19 by Peter Boughton posted on 12/23/2011 at 4:01 AM

There's an easier way to ensure it doesn't break for people that have an existing invoke function AND it's also a way that means you're not switching syntax when doing JavaScript.

s["sum"](x:4, y:9)

Comment 20 by Raymond Camden posted on 12/23/2011 at 4:04 AM

What can I say - we didn't do it that way.

Comment 21 by Peter Boughton posted on 12/23/2011 at 4:19 AM

Well I guess it has only been in the public bug tracker for six months, so we'll have to wait at least eighteen more for it to count as being "requested for years" and thus have a chance of being fixed. ;)

Comment 22 by salvatore fusto posted on 12/23/2011 at 2:25 PM

Ray, have i read correctly? you have written about closures (anonimous function, pass a fn as argument or return a fn eccin Zeus), didn't you?
i know that Sean Corfield has porposed this, and this could be is a great step forward for the language!!!
regards

Comment 23 by Raymond Camden posted on 12/23/2011 at 9:46 PM

Closures are definitely in Zeus. I will be blogging examples in January. You can see it right now in my MAX video.

Comment 24 by Ben posted on 12/24/2011 at 2:50 PM

Can you comment on the depth of closure support? Someone said it would be limited.

Comment 25 by Raymond Camden posted on 12/24/2011 at 8:25 PM

Define limited. It seems pretty good to me. When I blog it, you will see, and be able to comment obviously. :) My MAX video was cut off, but I'm pretty sure closures is in the part you can watch.

Comment 26 by Kurt Bonnet posted on 1/1/2012 at 4:48 AM

Very nice!!!! I love that I can use script syntax to perform this type of operation now!

I'm also VERY glad to see that implicit structure notation accepts COLONS as name/value pair delimiters. Since I do so much JS/Json work now I can't tell you how many times I have to go back and replace my equals signs with colons.

I can't wait for CF10 to come out!

Comment 27 by Kurt Bonnet posted on 1/1/2012 at 4:50 AM

Whoops, typo. I meant "I have to go back and replace my colons with equals signs" when I switch from JS to CF dev.

It'll be nice to just use colons on both sides.

Comment 28 by Markus Moser posted on 1/3/2012 at 9:31 PM

i'm a little bit confused about this function. you write the cfc can be provided as loaded cfc or as string declaration (like with the tag cfinvoke).
does this function only support cfc invocation or also webservice invocation like the tag does?
if webservice call are supported how this is working without named arguments?

tnx markus

Comment 29 by Raymond Camden posted on 1/3/2012 at 9:35 PM

It supports either a CFC instance or a CFC name. Either of those are not going to be remote. I did not try an instance of a web service but I'd imagine that wouldn't work.

Comment 30 by Sean Corfield posted on 1/3/2012 at 11:01 PM

Given that the CFML Advisory Committee was unanimous that object[method](args) should work in cfscript I'm a bit surprised to see yet another global function added. You, Ben Forta and Adam Lehman all supported the object[method](args) notation. The other CFML engines already support it and the Adobe feedback was that it was simply a little too late in the (CF9) process to add it. Yet now we're seeing a (deliberately?) different approach being taken in ACF?

Comment 31 by Sean Corfield posted on 1/3/2012 at 11:04 PM

BTW, so glad that ACF will support : in struct literals! Folks have been asking for this ever since struct literals were introduced in CF8.

And it'll mean ACF10 behaves like the other CFML engines have done for several years :)

Comment 32 by Raymond Camden posted on 1/3/2012 at 11:43 PM

Sean: I will admit, I would have preferred the other syntax as well. I can accept this version though.

Comment 33 by Sean Corfield posted on 1/3/2012 at 11:47 PM

I think it's yet another "icky" language decision but it's not out of band compared to several other poor decisions over the years that CFML has had to endure :)

And I can see where it's come from, given how many other dynamic languages have some sort of "invoke" method on a metaprogramming object...

Comment 34 by Raymond Camden posted on 1/24/2012 at 7:13 PM

Small correction folks. Zeus will not support the first argument of invoke being a string. Rather, it must be a CFC instance.