Yesterday, I used to be engaged on a sortable datagrid with server-side pagination; and I used to be writing logic to toggle between ASC and DESC instructions based mostly on the consumer’s present choice. It occurred to me {that a} extra generic perspective on this may be to take a “worth” after which “cycle” it by way of a sequence of values. As a enjoyable Friday code kata, I wished to do this in ColdFusion.
Contemplate the sequence of values:
[ "A", "B", "C", "D" ]
For a given worth — C — I would need to get the subsequent worth (D) or the earlier worth (B). If we consider the gathering as a “sequence”, we will use the widespread ColdFusion naming conference to ascertain two built-in features (BIFs):
-
sequenceNext( sequence, present )– locates the present worth; then returns the following ingredient by index. If the following index goes past the tip of the array, the primary ingredient is returned (biking again to the top of the sequence). -
sequencePrevious( sequence, present )– locates the present worth; then returns the earlier ingredient by index. If the earlier index goes past the top of the array, the final ingredient is returned (biking again to the tip of the sequence).
The native ColdFusion BIFs usually permit an argument to be both a worth or a closure. However I wish to separate these two issues into completely different operate signatures. Which signifies that we will create two extra BIFs that take a operate because the second argument:
sequenceNextWith( sequence, operator )sequencePreviousWith( sequence, operator )
I just like the suffix *With() to point that we’ll be performing the motion with the assistance of the passed-in operator. I might have carried out this with a type-check internally to a single technique; however, I would wish to have 4 strategies with crystal clear duties somewhat than 2 strategies with fuzzier duties. Your mileage could range.
Plus, the good factor about that is that we will simply fulfill the value-based comparability implementation with a one-line transformation that takes the static argument — present — and passes-it-on to the closure-based BIF fairly simply:
( worth ) => ( worth == present )
On this case, the worth is the iteration worth of the sequence being in comparison with the passed-in present argument.
With that stated, here is my implementation of those 4 ColdFusion features. I will cycle by way of a sequence of letter and output the prev/subsequent values per ingredient:
<cfscript>
// ColdFusion language extensions (world features).
embody "/core/cfmlx.cfm";
// ------------------------------------------------------------------------------- //
// ------------------------------------------------------------------------------- //
sequence = [ "A", "B", "C", "D", "E" ];
present = "A";
// Begin with "A", then cycle the present ingredient by way of the sequence 10-times. This
// is sufficient to exhibit the wrapping across the limits of the array.
for ( i = 1 ; i <= 10 ; i++ ) {
subsequent = sequenceNext( sequence, present );
earlier = sequencePrevious( sequence, present );
echo( earlier );
echo( " ← <mark>[ #current# ]</mark> → " );
echo( subsequent );
echo( "<br />" );
present = subsequent;
}
// ------------------------------------------------------------------------------- //
// ------------------------------------------------------------------------------- //
/**
* I cycle to the following ingredient within the sequence after the present (given) worth. The
* location of the present worth is decided by strolling from the top of the array
* and performing a easy high quality test. If the present worth is situated within the final
* index, the cycle wraps round to the primary index.
*/
public any operate sequenceNext(
required array sequence,
required any present
) {
return sequenceNextWith( sequence, ( worth ) => ( worth == present ) );
}
/**
* I cycle to the following ingredient within the sequence after the matching predicate. The
* location of the matching predicate is decided by strolling from the top of the
* array and performing an invocation towards the iteration worth. If the matching
* iteration worth is situated within the final index, the cycle wraps round to the primary
* index.
*/
public any operate sequenceNextWith(
required array sequence,
required operate operator // Predicate (worth) -> Boolean
) {
cfloop(
array = sequence,
index = "native.i",
merchandise = "native.worth"
) {
if ( operator( worth ) ) {
// Warning: NULL coalescing assumes that not one of the sequence components
// will probably be NULL, which I skinny is a good assumption.
return ( sequence[ i + 1 ] ?? sequence[ 1 ] );
}
}
throw(
kind = "CurrentNotFound",
message = "Present worth not present in sequence."
);
}
/**
* I cycle to the earlier ingredient within the sequence earlier than the present (given) worth.
* The situation of the present worth is decided by strolling from the top of the
* array and performing a easy high quality test. If the present worth is situated within the
* first index, the cycle wraps round to the final index.
*/
public any operate sequencePrevious(
required array sequence,
required any present
) {
return sequencePreviousWith( sequence, ( worth ) => ( worth == present ) );
}
/**
* I cycle to the earlier ingredient within the sequence earlier than the matching predicate. The
* location of the matching predicate is decided by strolling from the top of the
* array and performing an invocation towards the iteration worth. If the matching
* iteration worth is situated within the first index, the cycle wraps round to the final
* index.
*/
public any operate sequencePreviousWith(
required array sequence,
required operate operator // Predicate (worth) -> Boolean
) {
cfloop(
array = sequence,
index = "native.i",
merchandise = "native.worth"
) {
if ( operator( worth ) ) {
// Warning: NULL coalescing assumes that not one of the sequence components
// will probably be NULL, which I skinny is a good assumption.
return ( sequence[ i - 1 ] ?? sequence[ -1 ] );
}
}
throw(
kind = "CurrentNotFound",
message = "Present worth not present in sequence."
);
}
</cfscript>
Observe that I am utilizing the NULL coalescing operator (??) to implement the wrap-around conduct of the sequence biking. This means that not one of the sequence values will ever be NULL; which I feel is a good assumption for this kind of work.
If we run this Adobe ColdFusion 2025 code, we get the next output:
I truthfully do not understand how a lot this sort of performance would come up in my ColdFusion programming. However that is the enjoyable of the code kata — it simply will get you to consider the code, it would not must end in something instantly helpful.

