Ask a Jedi: Dynamic evaluation
Luis asks:
Do you know of any way to dynamically create the condition for an if statement? I think the best way to explain this is with an example. I'm looking do to something along the lines of the following
<cfset firstElement = "hello" />
<cfset operator = "eq" />
<cfset secondElement = firstElement />
<cfif firstElement operator secondElement></cfif>I've tried various methods and variations using cfscript, iif(), and combinations of evaluate() and de(). Additionally I've searched the usual suspects for answers. (coldfusion, cf docs, cfwack, cf advanced, etc...) I realize there are longhand ways around this such as using a cfswitch to evaluate the value of operator, but I'm hoping to be able to simply support all of CF's native operators without having to essentially write the same code for each operator choice.
Most likely you just had a typo when you tried evaluate(), and frankly, evaluate can be a bit confusing at times. This code sample worked for me:
<cfset first = "ray">
<cfset second = "ray">
<cfset op = "eq">
<cfoutput>#evaluate("first #op# second")#</cfoutput>
Switching second to "paris hilton" correctly returned a false value. Note though that in general, when I see evaluate I get a bit uneasy. Evaluate is not as slow as it used to be when you use ColdFusion 8. But it always strikes me as kind of a dirty function. Like - should I really be using this? I'm not telling folks to not use it (like I used to). I will say that most of the time when I do see it - it isn't necessary.
One of the classic examples was - I have a variable that points to another variable. How do I get the value? They would then do this:
<cfset variable = "name">
<cfset value = evaluate(variable)>
But with scopes, this is a lot simpler, and easier to read I think:
<cfset value = variables[variable]>
Comments
<cffunction name="op" returntype="boolean">
<cfargument name="opName" type="any" required="true">
<cfargument name="arg1" type="any" required="true">
<cfargument name="arg2" type="any" required="true">
<cfswitch expression="#arguments.opName#">
<cfcase value="and"><cfreturn arguments.arg1 and arguments.arg2></cfcase>
<cfcase value="or"><cfreturn arguments.arg1 or arguments.arg2></cfcase>
<cfcase value="not"><cfreturn not arguments.arg1></cfcase>
<cfcase value="eq"><cfreturn arguments.arg1 eq arguments.arg2></cfcase>
<cfcase value="neq"><cfreturn arguments.arg1 neq arguments.arg2></cfcase>
<cfcase value="gt"><cfreturn arguments.arg1 gt arguments.arg2></cfcase>
<cfcase value="lt"><cfreturn arguments.arg1 lt arguments.arg2></cfcase>
<cfcase value="contains"><cfreturn arguments.arg1 contains arguments.arg2></cfcase>
</cfswitch>
<cfreturn false>
</cffunction>
<cfoutput>#
op('or',
op('eq','foo','bar'),
op('contains','foobar','foo')
)
#</cfoutput>
Also, is there a good place to go to get centralized info on ColdFusion performance and tuning outside of the Wack 3 and the release notes I found from Adobe from 2004 and a few random resources?
Ex: This page is 2007
http://blog.brianflove.com/articles/2007/04/23/col...
And advocates avoiding evaluate and iif like the plague. But with normal ?: syntax absent in 8 I love iif and need to know the truth. Thanks!
I think to me it is more a matter of appropriateness. Many times I've seen people use evaluate() when they don't need to. So given the example of a dynamic form field, they may do:
<cfset key = "name">
<cfoutput>#evaluate("form.#key#")#</cfoutput>
Whereas this is just as valid, and in my mind, more appropriate:
<cfset key = "name">
<cfoutput>#form[key]#</cfoutput>
The ColdFusion 8 performance brief says that evaluate in 8 is 2.9x faster than 7.0.2
But I still don't know how fast that is. Oh well.
I agree with you on usage. I love array access notation almost more than life itself.
There are some super dynamic situations where evalute (my opinion) is the best and most readable option, which is why I'm looking into this.
Thanks!
