Skip to main content
Ben Nadel at the New York ColdFusion User Group (Apr. 2008) with: Clark Valberg and Nafisa Sabu and Rob Gonda
Ben Nadel at the New York ColdFusion User Group (Apr. 2008) with: Clark Valberg@clarkvalberg ) , Nafisa Sabu@nafisa13 ) , and Rob Gonda@RobGonda )

For Consideration: An ArrayFrom() Function In ColdFusion

By on
Tags:

In my previous post, I took a look at the Array.sublist() method in ColdFusion; and, demonstrated that in order to use it safely you have to create a copy of the .sublist() result. This got me thinking about JavaScript and the Array.from() method. The Array.from() method allows you to create shallow copies of other arrays and Array-like values. Would it be worth having something like an arrayFrom() built-in function (BIF) in ColdFusion?

The arrayFrom() function would be used to take an untrusted value and turn it into a trusted value. Going back to JavaScript for a moment, consider the Promise. The Promise object provides an API on which the consuming code can depend. And, if you are dealing with an untrusted Promise, you can use the Promise.resolve() method to convert the untrusted value into a trusted value.

In the following JavaScript snippet, we have an Object that presents a .then() method. This is not a Promise; and, does not implement the full Promise API - for example, it doesn't expose a .catch() method. However, we can turn it into a trusted Promise using Promise.resolve():

<script type="text/javascript">

	// NOT A PROMISE! Just an object that happens to have a then() method on it.
	var thenish = {
		then( callback, errorCallback ) {

			errorCallback( new Error( "Not kablamo!" ) );

		}
	};

	// By wrapping the "thenable" value in a .resolve() call, it will "cast" the UNTRUSTED
	// thenable object into a TRUSTED, native Promise implementation (by "following" the
	// thenable value). This ensures that the value you are working supports the full API
	// of your Promise library. In this case, we're using the native Promises, but if you
	// wanted to use something like Bluebird, you would "wrap" the value in a Bluebird
	// implementation in order to ensure the Bluebird API.
	Promise.resolve( thenish )
		.catch(
			( error ) => {

				console.error( error );

			}
		)
	;

</script>

This code takes the thenish value and upgrades it into a full Promise implementation.

The arrayFrom() would to the same kind of thing - take something that is "array like" and upgrade it to be a full, native ColdFusion Array. To see what I mean, let's convert both a Struct and a .subList() result into a native ColdFusion array:

CAUTION: Please note that the following code is just for the sake of discussion and is not intended to be robust or correct.

<cfscript>

	// A Struct that looks like an array with numeric indices.
	arrayishStruct = {
		"1": "foo",
		"2": "bar",
		"3": "baz"
	}

	// An ArrayList that is NOT DETACHED from its original list.
	arrayishSlice = [ "foo", "bar", "baz" ]
		.sublist( 0, 2 )
	;

	dump(
		label = "Array from arrayishStruct",
		var = arrayFrom( arrayishStruct ).append( "woot woot" )
	);
	dump(
		label = "Array from arrayishSlice",
		var = arrayFrom( arrayishSlice ).append( "woot woot" )
	);

	// ------------------------------------------------------------------------------- //
	// ------------------------------------------------------------------------------- //

	/**
	* I generate a native ColdFusion array from something that is "arrayish".
	* 
	* CAUTION: This is just for the sake of discussion - this is not intended to be a
	* robust imlementation of this method. It doesn't handle _any_ edge-cases at all.
	*/
	public array function arrayFrom( required any value ) {

		var nativeArray = [];
		var length = len( value );

		for ( var i = 1 ; i <= length ; i++ ) {

			arrayAppend( nativeArray, value[ i ] );

		}

		return( nativeArray );

	}

</cfscript>

Here, we have a Struct that has numeric, array-like keys; and, we have a "view" into an array that we want to detach into its own array. The arrayFrom() function is merely making shallow copies of both. But, by creating a native ColdFusion array, it exposes the full Array API, include the .append() member-method.

Two native ColdFusion array produced from untrusted array-like inputs.

As you can see, were able to append woot woot to both of the resultant values.

To be clear, it's not often that run into an "untrusted" value in ColdFusion. Typically, this would only be when you have to interact with a Java API that doesn't return a ColdFusion-castable Array (I don't really understand how all the magic in the CFML runtime works). So, this is definitely an edge-case. But, I thought it might make for an interesting language suggestion.

Want to use code from this post? Check out the license.

Reader Comments

Post A Comment — I'd Love To Hear From You!

Oops!
NEW: Some basic markdown formatting is now supported: bold, italic, blockquotes, lists, fenced code-blocks. Read more about markdown syntax »
Comment Etiquette: Please do not post spam. Please keep the comments on-topic. Please do not post unrelated questions or large chunks of code. And, above all, please be nice to each other - we're trying to have a good conversation here.