The replace function now accepts a callback

June 1, 2019
I try to bend the internet to my will.
Wizard 20 posts
Followers: 17 people
2

The replace function now accepts a callback

I try to bend the internet to my will.
Wizard 20 posts
Followers: 17 people
June 1, 2019

I was looking at the replace in-built function and noticed that it now accepts a callback. Here is the example that is shown on the docs.

myStr = "happy app application apply appreciate appreciation Apprentice";
outStr = replace( myStr, "app", function ( transform, position, original ) {
  return UCase( transform );
}, "all" );
writeoutput( outStr );

Whilst the example does indeed use a callback function, it doesn’t do anything that we couldn’t do with a regular replace. The above example could be written as:

outStr = replace( myStr, "app", "APP", "all" );

So this got me thinking – where would the callback be useful?

The callback function accepts transform, position, original arguments. Transform argument is the value being replaced, position is the position it is found in the string and original is the string it is operating on. Using these arguments the best I could come up with is something like this:

outStr = replace( myStr, "app", function ( transform, position, original ) {
  var maskIt = position > ( original.len() /2 );
  if ( maskIt ) {
    return repeatString( "*", transform.len() );
  }
  return transform;
}, "all" );
writeoutput( outStr );

This masks any matches after the midway point in the string, returning happy app application apply appreciate ***reciation Apprentice. So not exactly a useful bit of code.

Where it becomes a bit more useful is if you wanted to alternatively colour code the matches. To do that we’ll need to keep track of which match we are working with.

function alternatingHighlighter( oddColour, evenColour ) {
    var count = 0;
    return function( transform, position, original ) {
        count++;
        var colour = ( count % 2 ) ? oddColour : evenColour;
        return '#transform#';
    }
}

replacer = alternatingHighlighter( "red", "green" );
outStr = replace( myStr, "app", replacer, "all" );

This returns the original string but alternatively colour codes each match. Here’s an example if you want to try it:
https://cffiddle.org/app/file?filepath=5e3189ae-3673-4388-bf57-fe8740d5e86e/72b68581-3b48-40dc-acc6-a86d0e7ddf41/5790c11a-14ee-4e97-b80b-c4a5d686d8fb.cfm

replaceNoCase also supports a callback function, but when I tried that, the value of the transform argument is always uppercase, not the case of the actual matching bit of text. Taking the previous example above and switching it to use replaceNoCase like so:

myStr = "happy app application apply appreciate appreciation Apprentice";
outStr = replaceNoCase( myStr, "aPp", function ( transform, position, original ) {
  return transform;
}, "all" );
writeoutput( outStr );

The output is: hAPPy APP APPlication APPly APPreciate APPreciation APPrentice. Runnable code here:

https://cffiddle.org/app/file?filepath=c572036e-82a7-4557-81e6-67340b5b214f/caecb7e8-554a-4ce4-afd8-ceba0dec20b3/09299034-1ddd-4d20-b9cc-60bf155d7f3f.cfm

So, this may be a useful additional to the replace in-built function, but I struggled to find a use case for it where an reReplace wouldn’t be more useful. I would be interested to know how people are using it and if I am missing anything obvious!

Comments (2)
2019-06-06 20:53:47
2019-06-06 20:53:47

It works on ACF2016, ACF2018 and Lucee 5.

Just realised that the blog engine has stripped out the HTML to do the red / green colour coding. The runnable example has it in though.

Like
2019-06-06 19:29:06
2019-06-06 19:29:06

What is the lowest version of ColdFusion that supports this?

Like
Add your comment