I'm writing this so I can link someone to it. It's just what it says on the wrapper, so won't be of any interest to anyone who already knows this.
I still fairly frequently see people using pound-signs (#) in their CFML code when they don't need to. This also includes code in the CFML docs, which is concerning! Pound-signs seem to be the apostrophe's of the CFML world: people know they exist, and are necessary, but don't necessarily know the (fairly simple) rules, so "if in doubt, pepper them about".
However pound-signs have even more simple rules than apostrophe's. Here are a list of rules:
- Pound-signs are necessary when there is scope for a CFML expression to be interpreted as a literal string rather than an expression;
- err...
- ... that's it.
In tag-based code, outside of a tag
For example:<cfset aVariable = "A variable">
<cfoutput>
aVariable<br>
#aVariable#<br>
</cfoutput>
One needs the pound-signs around the variable reference so that the CFML parser knows it's a variable. This code outputs:
aVariable
A variable
Which demonstrates the difference.
Within an actual tag
For example:<cffunction name="f">
<cfargument name="x" default=getDefault()>
<cfargument name="y" default=#getDefault()#>
<cfoutput>#serializeJson(arguments)#</cfoutput>
</cffunction>
<cffunction name="getDefault">
<cfreturn "default value">
</cffunction>
<cfset f()>
This outputs:
{"Y":"default value","X":"getDefault()"}
Note the un-pound-signed default value is treated like a string. This is the one instance that - to me - is counter-intuitive behaviour.
When the expression is within a string
And for the same reason as the previous situation. Consider this code:
<cfset aVariable = "A variable">
<cfset message = "aVariable<br>#aVariable#">
<cfoutput>#message#</cfoutput>
Obviously (?) one needs to use the pound-signs there to identify the text as a variable, not as a string literal.
This also applies within tag attributes:
<cfset list = "tahi,rua,toru,wha">
<cfloop list="list" index="element">
<cfoutput>#element#</cfoutput><br>
</cfloop>
<hr>
<cfloop list="#list#" index="element">
<cfoutput>#element#</cfoutput><br>
</cfloop>
<hr>
This outputs:
list
tahi
rua
toru
wha
In the first loop, the list is literally the string "list".
Note that this also applies if the attribute value is not actually quoted:
<cfset list = "tahi,rua,toru,wha">
<cfloop list=list index=element>
<cfoutput>#element#</cfoutput><br>
</cfloop>
<hr>
<cfloop list=#list# index=element>
<cfoutput>#element#</cfoutput><br>
</cfloop>
<hr>
(same output as before).
CFML looks godawful if you don't quote your attributes, so just don't do that.
That's it. That's when you need to use pound-signs. So that's like: hardly ever.
When does one definitely not need pound-signs?
Well, other than "all occasions other than those I mentioned just before", here a are a coupla common cock-ups:
<cfset firstName = "Zachary">
<cfset lastName = "Cameron Lynch">
<cfset fullName = #firstName# & " " & #lastName#>
<cfoutput>#fullName#</cfoutput>
NO. Do not do that. It's just this:
<cfset fullName = firstName & " " & lastName>
Also one does not need to do this:
<cfif #someValue# EQ #someOtherValue#>
It's just this:
<cfif someValue EQ someOtherValue>
Why? Because we're already in the middle of a CFML statement, so the CFML parser is gonna assume that everything is CFML unless it's not (like it's a literal string).
Either/Or
Update:
Dan Skaggs put me onto this from his comment below.
Dan Skaggs put me onto this from his comment below.
There's at least one weirdo situation in which it doesn't matter if one uses pound-signs or not. Up until - and including - CF9, when one was looping over a query one, passed the NAME of the query, not the actual query, into the loop:
<cfset rainbow = queryNew("")>
<cfset queryAddColumn(rainbow, "id", "integer", [1,2,3,4,5,6,7])>
<cfset queryAddColumn(rainbow, "maori", "varchar", ["whero","karaka","kowhai","kakariki","kikorangi","tawatawa","mawhero"])>
<cfset queryAddColumn(rainbow, "english", "varchar", ["red","orange","yellow","green","blue","indigo","violet"])>
<cfloop query="rainbow">
<cfoutput>#id#: #maori# (#english#)<br></cfoutput>
</cfloop>
Note I'm passing the literal string "rainbow" there, not the query itself (which would be "#rainbow#"). Why CF used to behave like this is anyone's guess. One can pass a dynamic expression to a query loop, but the expression needed to evaluate to the name of the query, eg:
<cfset queryName="rainbow">
<cfloop query="#queryName#">
<cfoutput>#id#: #maori# (#english#)<br></cfoutput>
</cfloop>
However as of ColdFusion 10, one can either pass the name of the query, or the query itself, eg:
<cfloop query="#rainbow#">
<cfoutput>#id#: #maori# (#english#)<br></cfoutput>
</cfloop>
Cheers for the heads-up there Dan.
What else?
Don't call them octothorps. The person you're talking to will either:- not know what you're on about, which is a fail; Or:
- they will know what you're talking about, and just think you're a dick. Well if that person is me, anyhow ;-)
--
Adam
NB: I spelt it "apostrophe's" on purpose, before anyone decide's to point that out.