I use the # symbol around every dynamic value in my application and after posting some of my code on here for help, I've been told there's no need to use the # in many places e.g. <cfif> statements.
So I have started removing the # symbols, until I realised I broke my application because I removed the # symbols from the value="" attribute of a <cfprocparam> tag.
I am confused as to:
Why use the # symbol is some places and not others (and what is the benefit of not using it?)
Why if they are not required in <cfif> and <cfargument> tags are they suddenly required in <cfprocparam> tags?
Due to this lack of consistency, is it not better to just wrap hashes around every dynamic value in the first place?
There is no inconsistency (or very little: none of what you cite are inconsistencies), it's just you not understanding the rules (which are pretty basic really). It's all in the docs: "Using number signs"
In short, within a CFML statement, all elements are considered CFML, so there is no need to specifically mark them as such. EG:
<cfset myVar = someFunction(anArgument)>
There is no ambiguity there that myVar, someFunction and anArgument are anything other than CFML constructs, so no need to do this sort of thing:
<cfset myVar = #someFunction(anArgument)#>
As some people are inclined to do.
In the middle of text or within a string, there is ambiguity as to what's text and what's CFML, so one needs to use pound signs to mark them as such. EG:
<cfset myVar = "The time is #now()#">
It's necessary to us pound-signs there to disambiguate now() as being a CFML statement, an not just part of the string, eg:
<cfset myVar = "CFML has a function now() which returns the current timestamp">
Equally:
<cfquery>
SELECT col1
FROM table2
WHERE col2 = #someValue#
</cfquery>
There would be no way of knowing someValue is a variable there without marking it as such.
That's basically it. It's not complicated.
Rule 1: If you are inside of quotes, then you are pushing a string. If you want a substitution, the you use #name#
Rule 2: If you are inside of a <cfoutput>, you are generating a string.
While it is possible to write
<cfif "#name#" EQ "bob">Hi Bob</cfif>
It is easier to write
<cfif name EQ "bob">Hi Bob</cfif>
Rule 3: I think that <cfoutput query="qryData"> is kinda wrong, I have written it so much, I don't think much of it.
The # symbol is required around a variable only when you need to evaluate the contents of that variable. For example, when you need to out put that variable in a view.
You don't need them in cfset or cfif because the content of the variables is used in the Set or comparison.
You shouldn't be using the value of variables in the cfargument tag. You might however pass in a variable to as an argument without first evaluating it eg. myFunction(myarg=myVariable)
Cfprocparam you need to pass the value. You may be confusing how you're passing the variable and the value.
Value="myVar" would pass "myVar" as the value, where as value="#myVar#" would evaluate myVar and pass its content to value. value=myVar would pass myVar to value.
No real inconsistencies in the examples you give. That's not to say that there aren't a few inconsistencies kicking around in ColdFusion. ;)
Don't be hashing everything. It's messy and means that you add an evaluation step in everything bit of code you write.
Related
This question already has answers here:
How can I prevent SerializeJSON from changing Yes/No/True/False strings to boolean?
(7 answers)
Closed 6 years ago.
I'm currently setting a number of variables like so:
<cfset printPage = "YES">
Eventually, when I print these variables out, anything that I try to set to "YES" prints out as "true". Anything set to "NO", prints out as "false". I'm not opposed to using the YesNoFormat function. In fact I might end up using that function in this application, but in the mean time I would like to know if ColdFusion is actually storing the words "YES" and "NO" in memory, or if it is converting them to a boolean format behind the scenes.
If CF is storing my variables exactly the way that I declare them, how would I go about retrieving these variables as strings? If CF is changing the variables in some way, are there any special characters or keywords that I could use to force it to store the variables as strings?
Thank you to everyone that commented / answered. I did a little more experimenting and reading, and it seems that the serializeJSON function will automatically convert "Yes" to "true" and "No" to "false". I either need to deal with this problem in my javascript, or I can add a space in the affected properties to circumvent this behavior.
You already know how to display the boolean value as "yes" or "no" (using YesNoFormat()). I don't think there is a way to force ColdFusion to store a variable a certain way. It just doesn't support that. I guess you could call out the Java type directly by using JavaCast(). I just don't see why you would want to go through that extra work for something like this. You can certainly research that a bit more if you like. Here is a link to the document for JavaCast.
Have a look at this document regarding data types in ColdFusion. I will post some of the relevant points from that document here but please read that page for more information.
ColdFusion is often referred to as typeless because you do not assign types to variables and ColdFusion does not associate a type with the variable name. However, the data that a variable represents does have a type, and the data type affects how ColdFusion evaluates an expression or function argument. ColdFusion can automatically convert many data types into others when it evaluates expressions. For simple data, such as numbers and strings, the data type is unimportant until the variable is used in an expression or as a function argument.
ColdFusion variable data belongs to one of the following type categories:
Simple One value. Can use directly in ColdFusion expressions. Include numbers, strings, Boolean values, and date-time values.
Binary Raw data, such as the contents of a GIF file or an executable program file.
Complex A container for data. Generally represent more than one value. ColdFusion built-in complex data types include arrays, structures, queries, and XML document objects. You cannot use a complex variable, such as an array, directly in a ColdFusion expression, but you can use simple data type elements of a complex variable in an expression. For example, with a one-dimensional array of numbers called myArray, you cannot use the expression myArray * 5. However, you could use an expression myArray[3] * 5 to multiply the third element in the array by five.
Objects Complex constructs. Often encapsulate both data and functional operations.
It goes on to say this regarding Data Types:
Data type notes
Although ColdFusion variables do not have types, it is often convenient to use “variable type” as a shorthand for the type of data that the variable represents.
ColdFusion provides the following functions for identifying the data type of a variable:
IsArray
IsBinary
IsBoolean
IsImage
IsNumericDate
IsObject
IsPDFObject
IsQuery
IsSimpleValue
IsStruct
IsXmlDoc
ColdFusion also includes the following functions for determining whether a string can be represented as or converted to another data type:
IsDate
IsNumeric
IsXML
So in your code you could use something like IsBoolean(printPage) to check if it contains a boolean value. Of course that doesn't mean it is actually stored as a boolean but that ColdFusion can interpret it's value as a boolean.
I have a requirement to read the string with both single quotes and without quotes from a macro retrieve_context.
While calling the macro, users can call it with either single quotes or without quotes, like below:
%retrieve_context('american%s choice', work.phone_conv, '01OCT2015'd, '12OCT2015'd)
%retrieve_context(american%s choice, work.phone_conv, '01OCT2015'd, '12OCT2015'd)
How to read the first parameter in the macro without a single quote?
I tried %conv_quote = unquote(%str(&conv_quote)) but it did not work.
You're running into one of those differences between macros and data step language.
In macros, there is a concept of "quoting", hence the %unquote macro function. This doesn't refer to traditional " or ' characters, though; macro quoting is a separate thing, with not really any quote characters [there are some sort-of-characters that are used in some contexts in this regard, but they're more like placeholders]. They come from functions like %str, %nrstr, and %quote, which tokenize certain things in a macro variable so that they don't get parsed before they're intended to be.
In most contexts, though, the macro language doesn't really pay attention to ' and " characters, except to identify a quoted string in certain parsing contexts where it's necessary to do so to make things work logically. Hence, %unquote doesn't do anything about quotation marks; they are simply treated as regular characters.
You need to, instead, call a data step function to remove them (or some other things, but all of them are more complicated, like using various combinations of %substr and %index). This is done using %sysfunc, like so:
%let newvar = %sysfunc(dequote(oldvar));
Dequote() is the data step function which performs largely the same function as %unquote, but for normal quotation characters (", '). Depending on your ultimate usage, you may need to do more than this; Tom covers several of these possibilities.
If the users are supplying your macro with a value that may or may not include outer quotes then you can use the DEQUOTE() function to remove the quotes and then add them back where you need them. So if your macro is defined as having these parameters:
%macro retrieve_context(name,indata,start,stop);
Then if you want to use the value of NAME in a data step you could use:
name = dequote(symget('name'));
If you wanted to use the value to generate a WHERE clause then you could use the %SYSFUNC() macro function to call the DEQUOTE() function. So something like this:
where name = %sysfunc(quote(%qsysfunc(dequote(%superq(name)))))
If your users are literally passing in strings with % in place of single quotes then the first thing you should probably do is to replace the percents with single quotes. But make sure to keep the result macro quoted or else you might end up with unbalanced quotes.
%let name=%qsysfunc(translate(&name,"'","%"));
I want to learn how to add spaces in variable names.
I know that a lot languages prevent me from doing this, but I believe that there is a trick to do this because I saw someone did it in MQL5
A MetaTrader Terminal allows to show a UI-Dialogue Panel for MMI-assisted setting values for input and extern variables declared in { Expert Advisor | Technical Indicator | Script } code, during a code-execution launch.
( Ref. a picture below ): .
If you really want to be evil you can sometimes use the left-to-right mark, U+200E which looks like a regular space but is generally not considered whitespace. Different languages and/or specific platforms may behave differently.
This trick seems to work in C# and apparently you can do similar things in ruby.
I tried this using g++ and luckily for everyone's sanity it is not allowed:
foo.cc:5:10: error: non-ASCII characters are not allowed outside of literals and identifiers
int a<U+200E> b = 3;
Please don't do this outside of pranks and April fool's day jokes.
In C++ you can't put spaces in variable names but you can get what you want using a std::map.
For example:
#include <map>
#include <string>
int main()
{
std::map<std::string, std::string> vars;
vars["Time Frame"] = "15 minutes";
vars["Indicator Period"] = "16";
// ... etc
}
The std::map is an associative container that maps one std::string onto another.
Depending on how you intend to use the map you may also want to consider using an std::unordered_map which should have higher performance but will not keep the keys sorted and may have a higher memory usage.
As much as I know, there isn't any option to add spaces to variables name.
The trouble with using spaces in names (whether filenames, variable names or something else) is that you need to have some other mechanism for determining what is part of this name and what is part of the next section of code. Your sample looks like a form, so that has it's own formatting and structure.
SQL does allow you to "quote" variable names with either [name with space] or with backticks `name with space`.
Most other languages do not allow spaces in variable names, because any whitedspace is considered a separator for different lexical unit [different name/word/variable]. There is no way you can change this, as it would alter the meaning of "normal code". Most languages do allow/use _ as a "space in names" character.
Of course, if you have "variables" that are your own construct, read from for example a database or file, you can use your own syntax, and use for example std::map<std::string, sometype> or std::unordered_map<std::string, sometype> to connect the string from your data to the corresponding value.
Spaces (white space) are used in C++ to isolate keywords and variable names, thus they cannot exist in a variable name or the compiler will treat the text as multiple identifiers.
Example - valid: static const unsigned int my_variable = 6U;
If there is a space between my and variable how does the compiler know which is the variable name? If there are two variables here, it doesn't make sense.
Also, as you can see, there may be more than one keyword in a statement.
I find a solution .In Mql5 , when you add a comment next to the variable name , it will appear instead of the variable name .
See this image : http://prntscr.com/79vaae
When I prepare a statement with bindValue the placeholder mark is not replaced if it is surrounded with single quotes. This is problematic since in SQL strings are surrounded by single quotes to avoid keyword conflicts.
See my attachements with screenies of the content of the database once inserted with and once without single quotes.
I already reported a bug, but meanwhile I am not sure anymore if this is not just an encoding problem. Is it correct to use single quotes, i.e. should this work/ is this really a bug?
With quoutes
Without quoutes
It is not a bug. Just don't use the single quotes. The bindValue mechanism does not just replace your :path with a string in your statement. No risk of name conflicts. See it as some kind of different namespace. :-)
http://en.wikipedia.org/wiki/Prepared_statement: Prepared statements are normally executed through a non-SQL binary protocol, for efficiency and protection from SQL injection, but with some DBMSs such as MySQL are also available using a SQL syntax for debugging purposes.
http://en.wikipedia.org/wiki/SQL_injection#Parameterized_statements: With most development platforms, parameterized statements that work with parameters can be used (sometimes called placeholders or bind variables) instead of embedding user input in the statement. A placeholder can only store a value of the given type and not an arbitrary SQL fragment. Hence the SQL injection would simply be treated as a strange (and probably invalid) parameter value.
Are there any known functional or performance differences in using yes|no vs. true|false?
ColdFusion documentation states that values for boolean-type attributes are specified with yes/no. For example, <cfargument required="yes|no" ....> I have used true and false in place of yes|no and have seen no unexpected functionality.
[EDIT]
I appreciate the responses, perhaps I am thinking a bit more general in this case.
ColdFusion documentation states that the expected value is 'yes|no' for some parameters, such as for cfargument required. Is there any insight into why yes|no is documented as the only expected values, rather than also true|false or stating 'any boolean value' is expected? Seems a bit ambiguous to not indicate any boolean type rather than only state 'yes|no' if either A)We are to assume 'any boolean' B)There is an actual performance difference. Thoughts?
ColdFusion evaluates yes/no, true/false, 1 (or any non-zero number)/0 equally. This makes it easy to make shortcut booleans like <cfif myquery.recordcount> or <cfif len(FORM.myVar)> without having to convert the integer into a true/false.
"yes/no" is a few characters less to type.
"true/false" (and true/false) is more in line with other programming languages.
In terms of performance, they are all strings as far as CF is concerned. It is not until you try to use them in conditional logic that they magically change into other data types, like java.lang.Boolean. The conversion between strings and Booleans and back again is very fast. It's what CF does most of the time. You'd be hard pressed finding any reliable tests proving one faster than the other.
For code maintainability/readability it's best to stick with one or the other.
Some legacy CF tag functions specifically require "yes/no". They simply will not work with "true/false". I believe this is no longer the case in CF9+.
Don't rely on the ColdFusion documentation being accurate or up to date. Almost all of the methods that list "yes/no" as the default/allowed values actually support any kind of boolean value. "yes/no", "true/false", true/false, 1/0, etc.
IMHO using "yes/no" for booleans is crazy. Backwards compatibility from the old CF5 era. Sucks that Adobe are still using it to output java Booleans.
eg. writeDump( var: (not true) ); gives you "NO". But, I wanted false?! Grrr.
You can tell what java class your variable is currently by calling myVar.getClass().getName(). You can use it to watch CF casting your data from Boolean to String and back to Boolean again, like magic.
As an experiment, you could try this. For me, ten million iterations of not using "yes" resulted in 100 fewer milliseconds for the most part.
<cfscript>
bln = true;
starttime = getTickCount();
for(i=0;i<10000000;i++){
if(bln eq true)
foo="bar";
}
writeOutput(getTickCount()-startTime & '<br />');
starttime = getTickCount();
for(i=0;i<10000000;i++){
if(bln eq "yes")
foo="bar";
}
writeOutput(getTickCount()-startTime & '<br />');
</cfscript>
We just upgraded a project to CF2016 and suddenly began getting java.lang.VerifyError "Incompatible argument to function" errors. Turned out to be in cfform, we were using accessible="true". Changing the value to "yes" does not remove the error. Removing the entire "accessible" form tag does. Rather than figuring out what Flash-related nightmare this represents, we removed it from our forms.
Thanks, Adobe.