Most SAS programmers are familiar with the array in the Data Step. Fewer know about the PROC FCMP Array. In many ways the two are similar. Both associate a name with a list of variables or values. However, the two differ in quite a few ways. Today, I investigate the differences between the Data Step Array and the PROC FCMP version.

The PROC FCMP Array Documentation lists four points that apply only to the FCMP. I will dive into all four, along with two extra differences, that deserve attention. Some are self explanatory. Some require more explaining.

All Array References Must Have Explicit Subscript Expressions

This means: There is no such thing as an Implicit Array in PROC FCMP. An implicit array is referenced by its index variable. In the data step code below, i is the index variable of a. When I set i=3, this points to the third element of a. I do not have to specify an explicit index of a when I reference it.

data _null_;
   array a (i) a1-a3  (1 2 3);
   i=3;
   put a=;
run;

This is not allowed in the Function Compiler Procedure. When I run the same code as above, I get a syntax error in the log. SAS simply does not recognize the code

proc fcmp;
   array a (i) a1-a3  (1 2 3);
   i=3;
   put a=;
quit;

PROC FCMP Uses () After a Name to Represent a Function Call

In the SAS Data Step, I can reference the n’th element of an array with {}, [] and (). I typically use the square brackets. You are free to use whichever you like in the data step. See the code below.

data _null_;
   array a {3} (1 2 3);
   b=a(1);
   put b=;
run;

However, PROC FCMP allows only {} and []. This is because regular parenthesis () are restricted to function and soubroutine calls only. My advise: Use [] when you reference array elements in both. This serves consistency and you are not at risk of confusing it with a function call.

proc fcmp;
   array a {3} (1 2 3);
   b=a(1);
   put b=;
quit;

PROC FCMP Arrays Do Not Support Lower Bounds

In the SAS Data Step, I can do the following. This creates an array a with three elements, indexed at 0, 1 and 3. Controlling lower bound indexes in array can be quite handy. For example, see the post Use Temporary Arrays to Store Lagged Values in SAS.

data _null_;
   array a {0:2} (1 2 3);
   b=a[1];
   put b=;
run;

This is not allowed in PROC FCMP. It allows single number specifications for each dimension (in this case we have only 1 dimension). The code below yields a syntax error. SAS does not recognize the : as it does not expect a list.

proc fcmp;
   array a {0:2} (1 2 3);
   b=a[1];
   put b=;
quit;

You Can use a Maximum of six Dimensions for an Array.

The Data Step array allows as many dimension as your environment can handle. See the code below.

data _null_;
    array a {1, 1, 1, 1, 1, 1, 1};
run;

This is not the case in PROC FCMP. Here, you are limited to six dimensions. Consequently, the code below yields the error: “The array a has more than six dimensions. Only six dimensions are allowed”. I mention this only for completeness. I have never encountered a situation that requires more than 6 dimensions in an array.

proc fcmp;
   array a {1, 1, 1, 1, 1, 1, 1};
quit;

_temporary_ = /Nosymbols

When we specify the _temporary_ keyword in the data step, SAS does not create variables in the PDV for each element. Consider the code below. If we do not specify the _temporary_ keyword, SAS initializes the variables a1, a2 and a3 in the PDV. Temporary arrays are handy in so many situations. For example, we can use them to perform Array Lookups in SAS.

data _null_;
    array a {3} _temporary_ (1 2 3);
    b=a[1];
    put b=;
run;

The same functionality is available in PROC FCMP. However, there is a difference. Though, only by name. In the code below, we use the /Nosymbols Option to spcify that SAS should not create associated element variables. Consequently, we can reference the elements by subscripts. Not by variable names. Why SAS chooses two different keyword for the same functionality is beyond my comprehension.

proc fcmp;
    array a {3} / nosymbols (1 2 3);
    b=a[1];
    put b=;
quit;

The Size of an FCMP Array is Dynamic.

When we specify an array in the SAS Data Step, the size is fixed. We can not create an array with 3 elements, realize that we actually need 5 and then resize. That is why SAS programmers resolve to the ‘big enough’ principle when they create arrays. Often you see arrays specified with 9999999 elements. Just to be on the safe side.

Many SAS programmers (this one included) are surprised to learn that this is not the case in PROC FCMP. Here, we can actually change the size and dimensions of an array. We do this with the Call Dynamic_Array Routine. We can even Read and Write Data to FCMP Arrays. See the code below for a small example.

proc fcmp;
    array a {3} / nosymbols (1 2 3);
    call dynamic_array(a, 5);
    b=a[4];
    put b;
quit;

Wouldn’t it be great if this was possible in the SAS Data Step? We could get rid of that ‘big enough’ principle once and for all? Sadly, it is probably easier said than done. The SAS Data Step and the FCMP Procedure are two very different constructs. While the SAS Data Step compiles, then executes, PROC FCMP is an interactive procedure. Meaning that it runs whatever it encounters chronologically. There is no initial compilation phase to complicate things. This makes it much more flexible in terms of arrays and matrix operations. I will return to this topic in future blog posts.

Summary

In this post, we have investigated the difference between the array in the SAS Data Step and in PROC FCMP. Two seemingly equal constructs. However, they differ in quite a few ways. Perhaps most interestingly, we learn that the Data Step version is a fixed size, while the FCMP version is dynamic. That is why you can not modify the size of an Array you Pass to a Function or Subroutine. I use the FCMP Array in the post The Danish CPR Number in SAS.

If you are interested in data constructs in PROC FCMP, read the two posts Use SAS Hash Object in PROC FCMP and The SAS Hash Object as a Cache in PROC FCMP.

You can download the entire code from this post here.