Build an Embedded Array Language in Java : Page 3

This article describes a generalized system for dealing with multidimensional arrays of data. It lets you transform and extract slices of data along various axes with very little code, in the style of the programming language APL. And you're not limited to numerical data; you can generalize systems such as this to any kind of tabular data.

by Greg Travis

Jul 13, 2005

Page 3 of 3

Adding Dimensions
So far, you've dealt with only one-dimensional arrays, which isn't really very challenging. So let's add more data. Creating a two-dimensional cube is just like creating a one-dimensional cube, only you need two dimensions of data:

Figure 4. A Two-dimensional Cube: The figure shows a visualization of the data in a two-dimensional cube.

Map works on a two-dimensional array just like it did on a one-dimensional array. Applying 'doubler' to this gives you what you would expect, as shown in Figure 5:

A fold works just fine on a two-dimensional array as well. Remember that a fold reduces the number of dimensions by one. Just as you used fold to turn a one-dimensional array (10, 20, 30) into a single number value (the sum 60), you can use a fold to turn a two-dimensional array into a one-dimensional array:

Figure 5. A Doubled Two-dimensional Cube: Doubling works on a two-dimensional cube just as it does on a one-dimensional cube.

Cube f = cube.fold( 'plus', 0 );

Folding the cube that way results in a single column of values, as shown in Figure 6.

Figure 6. A Folded Two-dimensional Cube: Folding works on multi-dimensional cubes as well.

Playing with Axes
In higher dimensions, you may often it useful to move the axes around. For example, you might want to swap the axes of the two-dimensional array from the last section. That is, you might want to turn the array shown in Figure 4 into the form shown in Figure 7.

The array { 1, 0 } controls how to build the output array. In this case, the code will change the array so that axis #1 of the input becomes axis #0 of the output, and axis #0 of the input becomes axis #1 of the output. In other words, the code swaps them.

Map and fold are powerful operations. Their power lies in the fact that they don't actually describe the computation to be performedthey only describe the way to traverse the data. The computation itself is passed in as a Fun or Fun2.

This separation of traversal from computation is a staple of functional programming; it also touches on the "separation of concerns" idea from Aspect-oriented programming. Thus, the maps and folds shown here are only the beginning; it's up to you to create new functions to map and fold across your data structures.

Greg Travis is a Java programmer and technology writer, living in New York City. After spending three years in the world of
high-end PC games, he joined EarthWeb, where he developed new technologies with the then-new Java programming language. Since 1997, he has been a consultant in a variety of Web technologies.