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 dynmeth = "test"> <cfset res = invoke(s, dynmeth)>
<cfdump var="#res#">
<cfset s = new some()>
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.
Archived Comments
Cool. But what's wrong with a good old
compObjStr = "com.whatever";
compObj = createObject("component" , compObjStr );
Gr
Yuri
I think you misunderstood. This isn't about creating a dynamic CFC. It is about calling a dynamic method on a CFC.
Indeed!
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.
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.
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.
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!!
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).
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'});
"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.
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.
Love the JSON struct notation. That's definitely going to save me tons of time.
Is this invoke function instead of fixing obj[method](args) syntax? :/
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. :)
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.
Heh good point there. ;)
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?
You said it - too late now. ;)
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)
What can I say - we didn't do it that way.
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. ;)
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
Closures are definitely in Zeus. I will be blogging examples in January. You can see it right now in my MAX video.
Can you comment on the depth of closure support? Someone said it would be limited.
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.
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!
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.
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
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.
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?
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 :)
Sean: I will admit, I would have preferred the other syntax as well. I can accept this version though.
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...
Small correction folks. Zeus will not support the first argument of invoke being a string. Rather, it must be a CFC instance.