I was wondering whether ColdFusion uses any binary search algorithm for searching? Does anyone of you have any idea on in-built functions and what they use?
Coldfusion lets you use anything in the Java standard library.
<cfset arr = [1, 2, 3, 4]>
<cfset collections = createObject('java', 'java.util.Collections')>
<cfdump var="#collections.binarySearch(arr, 3)#">
Keep in mind that the returned value is zero-indexed, while CF is one-indexed.
You may need to do more complicated conversions depending on the data types inside your array, and of course the array must be sorted before you use binarySearch.
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 been reviewing asm.js, and I know one of the thing it does is use bit-wise operations to force numbers to be integers
If instead of
<cfreturn x>
If I
<cfreturn BitOr(x,0)>
Does this ensure that I am returning only integers as opposed to a float representation of an integer?
You can use JavaCast() to ensure that only integers are returned from ColdFusion.
<cfreturn JavaCast( "int", x )>
Depending on the version of ColdFusion, you may have an issue with serializeJSON() converting that value to a string though. In that case, then Miguel's suggestion of using parseInt() in your JavaScript would apply.
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.
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.
I would like to know if it's possible to use the content of a variable list of strings to create a new variable.
As an example:
str={"cow","monkey"}
these strings are extracted from a file. Now I would like to refer to these strings as if it was a variable. So the variable cow could be set to {4,2,3} or anything else. Any reference as str[[1]] gives the string "cow" of course.
Any clues or is this a bad idea anyway?
Of course I could add info in the list I already have such as:
str={{"cow",{4,2,3}},{"monkey",{}}
but then I still won't be able to directly address cow as a variable.
The simplest would be to just manually use symbols cow and monkey rather than strings:
In[309]:=
cow = 1;
monkey = 2;
{cow, monkey}
Out[311]= {1, 2}
But this is probably not what you asked. If you want to automatically convert strings to variables, then
what you have to do (if I understood the question correctly) is to first convert your strings to symbols, since symbols can be assigned values and used as variables:
Remove[cow,monkey];
str = {"cow", "monkey"};
str1 = ToExpression /# str
{cow, monkey}
(I assume that symbols cow and monkey have not been used/defined). After that, you can use the answer for this question to assign to the variables based on their positions in str1. However, the usefulness of this approach is also questionable.
What I think makes the most sense is to create so called indexed variables, such as
myIndexedVar["cow"] = 1;
myIndexedVar["monkey"] = 2;
where myIndexedVar is essentially a hash-table of key-value pairs, with keys being your strings and values being whatever you want to assign to them. The process can be automated if needed.
EDIT
To illustrate assignments to such variables, here is a function which automates that:
assignVariables[varNames_List, values_List, hashName_Symbol ] /;
Length[varNames] == Length[values] :=
MapThread[(hashName[#1] = #2) &, {varNames, values}];
Here is how you can use it:
In[316]:= assignVariables[str,{{4,2,3},{}},myIndexedVar]
Out[316]= {{4,2,3},{}}
In[317]:= myIndexedVar["cow"]
Out[317]= {4,2,3}
In[318]:= myIndexedVar["monkey"]
Out[318]= {}
But again, this really is a hash-table, so your question makes most sense to me when reformulated as: "I want to make a hash-table with string keys. What's the easiest way to do that in Mathematica, add key-value pairs and access them". The answer seems to be - indexed variables, as illustrated above. You may also find it useful to read on DownValues, since these provide the mechanism for indexed variables.
Leonid's last method is probably the best, but I am fond of replacement rules, therefore I offer:
str={"cow","monkey"};
rules = {"cow" -> {4,2,3}, "monkey" -> {}};
str[[1]] /. rules
Out = {4, 2, 3}
See Rule, and ReplaceAll for more.
ToExpression will convert a string to an expression. Symbol["x"] creates the symbol x as the name suggests.
However, I wonder how you plan to use them. If you don't know a priori what's in the file with names how are you going to use them? If str={"cow","monkey"} and I create a list of symbols with strSym=ToExpression/#str then the only way I could continue in my code is to index this second array. I cannot simply say cow=5 in my code because I don't know at the time of writing the code that there will be a variable named cow.
In[1]:= str = {"cow", "monkey"};
strSym = ToExpression /# str
Out[2]= {cow, monkey}
In[3]:= strSym[[1]] // Evaluate = 5
Out[3]= 5
In[4]:= ?cow
Global`cow
cow=5
As you can see, indexing also requires an additional Evaluate, because Set (=) has HoldFirst as Attribute. So I can't set cow by indexing unless I have the index evaluated otherwise I overwrite the definition of strSym[[1]] .