Fat Arrow Function Support in Lucee 5 and Adobe ColdFusion 2018
Arrow functions have been around in CFML since Lucee 5 and Adobe ColdFusion 2018 (Update 5), respectively. Despite this, I only recently began trying to get comfortable with the syntax. I was surprised to find that, while Lucee added fat arrow support much earlier, Adobe ColdFusion provides more complete support for the syntax.
On the Arrow Function Syntax
Whether you like its succint nature, or find it off-putting, the arrow function syntax is here to stay. I believe it's worth learning, even if you don't intend to use it; otherwise, the arrow functions you stumble upon in someone else's code will be an indecipherable mess of parenthesis and greater than signs.
I don't intend this post to be a primer on (fat) arrow functions. For that, I'd recommend:
- Ben Nadel on Fat-Arrow Functions (ColdFusion primer)
- Adobe ColdFusion documentation on Lambdas (official docs)
- MDN docs on Arrow Functions (examples - while JavaScript, still helpful)
- Fat Arrow Functions in CFML (my live-coding exploration of the topic)
Engine Differences (Lucee 5 vs. Adobe ColdFusion 2018)
As I mentioned at the top, Lucee introduced support for arrow functions in Lucee 5, which was released in November of 2016. It wasn't until September 2019, with update 5 to ColdFusion 2018, that Adobe also supported the syntax.
Fat Arrow Syntax Supported by Both Engines
The following basic examples, some of which were cribbed and slightly modified from Ben's blog post above, are supported by both Lucee 5 and ACF 2018.
Basic
greet = ( name ) => {
return( "Hello, #name#." );
};
writeOutput( greet( "Matthew" ) ); // Hello, Matthew.
Dropping return
and curly brackets
// When the only statement is `return`
// we can remove `return` and the surrounding curly brackets
depart = (name) => "Goodbye, #name#.";
writeOutput( depart( "Marcy" ) ); // Goodbye, Marcy.
Without parameters
shrug = () => "¯\_(ツ)_/¯";
writeOutput( shrug() ); // ¯\_(ツ)_/¯
Within iterators
Examples of iterators include the array .map()
member function, arrayMap()
, and similar.
cuts = [ "julienne", "chiffonade", "dice" ];
upperCuts = cuts.map(
( item, index ) => {
return item.ucase();
}
);
writeDump( var='#upperCuts#', abort='true' );
// ["JULIENNE","CHIFFONADE","DICE"]
Syntax Supported only by Adobe ColdFusion 2018
The final three examples work in Adobe ColdFusion 2018, but result in a syntax error in Lucee. I found this a bit disappointing; hopefully this incompatibility/shortcoming is addressed soon.
Update - 06/04/2020: Within a few minutes of my publishing this, John Berquist provided a very insightful comment below, pointing out that the primary root of the incompatibilities I encountered is explained the Lucee issue LDEV-2417 - namely, that fat arrow functions shouldn't require parentheses around a single parameter.
Without parentheses
// Parentheses are optional when there's only one parameter name
greet = name => "Hello, #name#.";
writeOutput( greet( "Matthew" ) ); // Hello, Matthew.
Without return
and curly brackets, within iterators
// Oops. In the comments, John pointed out that this incompatibility doesn't have to do with the arrow function, but rather with how Lucee/ACF differ in their parsing of the semicolon in the function.
cuts = [ "julienne", "chiffonade", "dice" ];
upperCuts = cuts.map(
( item, index ) => item.ucase();
);
writeDump( var='#upperCuts#', abort='true' );
// ["JULIENNE","CHIFFONADE","DICE"]
Shorthand, within iterators
cuts = [ "julienne", "chiffonade", "dice" ];
lengths = cuts.map(cut => cut.len());
writeDump( var='#lengths#', abort='true' ); // [8,10,4]
Obviously, there are likely variations and edge cases that I haven't covered. If you find one, let me know in the comments.
Lucee Issues
There are a number of Lucee tickets related to this. Here's one, for example: LDEV-2417. Brad Wood also put together a Github repo demonstrating the incompatibilities. So, if this is something that interests you, make it known on those tickets!