Overview
In Adobe ColdFusion (2016 release), the language enhancements that have been introduced are safe navigation operator (“?.”) and collections support along with some other minor enhancements.
Safe navigation (?.)
You can use the safe navigation operator to access members of a Struct or values of an object.
Instead of ".", using the safe operator ensures that exception is not thrown when the variable is not defined.
Sample usage - 1
<cfoutput>#employee?.getDesignation#</cfoutput> or <cfoutput>#employee?.getDesignation()#</cfoutput>
This code does not throw exception even if variable employee is not defined. If employee is defined, then it works like a dot operator.
If safe navigation evaluates to an undefined value and if that value is assigned to a variable, usage of such variable could lead to an exception. For example, <cfset x = employee?.getDesignation>. In this example, if variable employee is not defined, then x is assigned as undefined.
Simple usage
<cfscript> function employees() { return {Marketing : "Tim", Sales: "John", Finance: "Andrew"}; } writeOutput("Employee in Finance: "); /** In earlier ColdFusion versions **/ emp = employees(); if(isDefined("emp") and isDefined("emp.Finance")) { writeOutput(emp.Finance); } else { writeOutput("Sorry, no employee found"); } /** Now with Safe Navigation**/ writeOutput(employees()?.Finance?:"Sorry, no employee found"); </cfscript>
Chaining
writeOutput(employee?.name?.firstname?.trim());
The above code does not output any value if any of the following is undefined/null:
employee OR
employee.name OR
employee.name.firstname.
writeOuptut(employee?.name.firstname.trim());
This code throws an exception if employee is defined but employee.name is undefined.
Sample usage - 2
Current code
<cffunction name="employee">
<cfreturn >
</cffunction>
<cfoutput>#employee()#</cfoutput> //prints empty string(default behavior)
<cfoutput>#employee().trim()#</cfoutput> //throws error - Value must be initialized before use
Safe Navigation Operator code
<cffunction name="employee">
<cfreturn >
</cffunction>
<cfoutput>#employee()?.trim()#</cfoutput> //Does not print any output
Scope search
Generally, a referenced variable is searched in various scopes before a match is found. In cases where a variable is not found in common scopes like function, local scope, and variable scopes, the search continues in implicit scopes, which can take a while. Implicit scope search can be disabled by using a new application setting called searchImplicitScopes in Application.cfc. It accepts a boolean value.
When set to false, an unscoped variable is not searched in implicit scopes and helps to find variables defined in the application faster.
For more information, see ColdFusion application variables.
Collection support (Ordered)
StructNew("Ordered") creates a struct that maintains insertion order.
All other ways of creating struct make normal struct without breaking backward compatibility.
Currently, keys are fetched in random order while looping over the struct. But, when you loop over the struct using StructNew(“Ordered”), keys are fetched according to the insertion order.
All other properties and functions work as a normal struct.
Example
<cfscript> departments = structNew("Ordered"); /** On iterating this struct, you get the values in insertion order, which is the way you inserted the values. **/ /** Create a structure and set its contents. **/ departments.John = "Sales"; departments.Tom = "Finance"; departments.Mike = "Education"; departments.Andrew = "Marketing"; /** Build a table to display the contents **/ </cfscript> <cfoutput > <table cellpadding="2" cellspacing="2"> <tr> <td><b>Employee</b></td> <td><b>Department</b></td> </tr> <!--- Use cfloop to loop through the departments structure.The item attribute specifies a name for the structure key. ---> <cfloop collection=#departments# item="person"> <tr> <td>#person#</td> <td>#Departments[person]#</td> </tr> </cfloop> </table> </cfoutput>
Literal syntax
In the 2016 release of ColdFusion, you can create an empty ordered structure implicitly, as in the following example:
<cfset myStruct = [:]> OR <cfset myStruct = [=]>
The following example shows how to create struct from literal syntax:
departments = [Marketing = "John", Sales : [Executive : "Tom", Assistant = "Mike"]];
Arrays
Pass by reference
By default, arrays are passed by value, which is slower as compared to passing arrays by reference. You can now choose to pass arrays by reference by using a new application setting called passArrayByReference. It accepts a boolean value.
When set to true, if an array is passed as a UDF argument, it is passed by reference.
Whitespace management
Adobe ColdFusion (2016 release) has a new way of managing whitespaces. In the administrator, the server level setting that used to suppress whitespaces at runtime can suppress them now at compile time.
Other enhancements
Adobe ColdFusion (2016 release) includes the following enhancements:
ArrayFindNoCase
Array(first argument) should be array of Strings or Boolean or Numeric only. And object to search(second argument) should be either String or Boolean or Numeric. Otherwise it throws an exception.
replaceListNoCase
It is the non case-sensitive version of replaceList.
cfloop tag
A new attribute "item" is introduced in array cfloop for file and list. Earlier, only index was supported in cfloop which was not a clean behavior. Now, you can use both item and index or either of them.
- If item and index are present, item holds the element and index holds the index.
- If only item is present, item holds the element.
- If only index is present, index holds the element (to support backward compatibility)
cfcollection tag
In Adobe ColdFusion (2016 release), the path attribute is ignored. All the collections are created in the collections directory at the location specified in Solr_Home field in the ColdFusion administrator.
For more information, see cfcollection.
arrayNew
ColdFusion 2016 comes with support for unsynchronized arrays. You can create unsynchronized arrays by passing a special flag to the arrayNew function. By default, the arrays are synchronized for backward compatibility. Note that unsynchronized arrays are not thread safe. You should use them when you do not need thread safety.
Set the isSynchronized flag to false to create an unsynchronized array.
Syntax:
ar_obj = arrayNew(numeric dimension, boolean isSynchronized);
For more information, see arrayNew.
Miscellaneous fixes
4018168 |
When a web service returns array, the client side receives it as Object[]. So ArrayAppend was adding the whole Object[] as an element in the destination array. Changing the behavior in web service client to create Array from Object[] and return introduces backward compatibility issue for existing webservice clients. In the ArrayAppend function, if the second argument to add is an Object[], you can merge Object[] into destination Array. |
3791418 |
When you register RESTful web services using auto registration, the “useHost” attribute’s default value changes “true”. Now, you can register a REST service with the host name that initializes the application. So you cannot access the REST service through any other host. |