Arrays as function arguments

When calling a function we commonly pass one or more parameters to that function. In most cases these are simple variables; integers or floats, but could be lists or arrays. In the case of passing arrays there is a hidden danger.

Let’s consider a simple function:

To use this function we pass two values, x and y, and the function returns the product.

Nothing surprising so far, and if we look at our variables there is nothing surprising there either:

Now let’s try something similar passing arrays as arguments. For this example we will pass two arrays of equal length, and multiply each ‘nth’ value of one array with the ‘nth’ value of the other:

Everything is still as expected, but let’s now make one slight change:

Note the final line. Why / how did the value a2 change? Other than the initialization there is no obvious indication that a2 will change.

The answer to this mystery is in understanding SETF.

The ‘setf’ special form evaluates the field ‘placeN’ and sets ‘exprN’ as it’s value.

In our function ‘product’, we did not only set the elements of a locally contained ‘x’, we set the evaluated elements of ‘x’. In other words, Nyquist looks up what ‘x’ is and sees that it is array ‘a1’, and then sets the value of each of its elements. Thus, not only is the array ‘x’ changed, but also it’s parent ‘a1’ is changed.

Not only does this provide opportunities to create difficult to find bugs, but raises the question “how do we prevent this from happening?” If we want to pass an array as an argument to a function and we do not want the value of the array to change, how do we ensure that it doesn’t?

The obvious solution might seem to be that we just need to ensure that ‘x’ is local to the function – perhaps something like:

However, that does not work – it is not a solution. When the variable ‘x’ is evaluated┬á it still points back to our original ‘a1’ array, and the result is the same – ‘a1’ is modified:

To get this to work in the way that we want (not changing ‘a1’), we must create a new array that is local to the function. We can then safely set the values of its elements and use it to provide the return value:

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.