IDL version 8.0 or greater: Negative Array Indices and the WHERE() function
Topic:
IDL 8.0 introduces the ability to index an array with a negative value. Many modern languages such as Ruby, Pearl, PHP, and Python also use this convention. This can be advantageous when you need to refer to the last index of an array without having to know how many elements exist in the array. For example the following statement:
PRINT, array[N_ELEMENTS(array)-1] |
can be reduced to:
Larger negative numbers are also accepted. For example,
array[-3] would refer to the third element from the end of the array. Prior to IDL 8.0, this was not possible.
Given this new behavior, it is of increased importance to be diligent in checking the output of the
WHERE() function. The
WHERE() function can be used to test for a value or a range of values in an array given a boolean criterion. All array indices referring to the values in the array that evaluate to true given this criterion are returned by the
WHERE() function. If no values are found, a value of
-1 is returned.
Prior to IDL 8.0, if the result from the
WHERE() function were equal to
-1, indicating no matches, and this value was passed to an array as an index, an error would be thrown indicating that the subscript was out of range. In IDL 8.0 however, a negative index is allowed, which will lead to the last element of the array being accessed, perhaps unintentionally, with no error thrown. This may lead to unintended results.
Discussion:
When using the
WHERE() function, it is important to check its returned result prior to using that result in any array indexing operations. Since IDL 8.0 now allows for negative subscripts to be used when indexing an array, the following behavior change is observed when comparing with past versions of IDL:
-
IDL 7.1:
IDL> array = bindgen(5)
IDL> print, array
0 1 2 3 4
IDL> w = where(array gt 4)
IDL> print, w
-1
IDL> print, array[w]
% Attempt to subscript ARRAY with W is out of range.
% Execution halted at: $MAIN$ |
-
IDL 8.0:
IDL> array = bindgen(5)
IDL> print, array
0 1 2 3 4
IDL> w = where(array gt 4)
IDL> print, w
-1
IDL> print, array[w]
4 |
It has always been important to check this result, but this has become especially true with IDL 8.0. To ensure that the last element of the array is not unintentionally referenced, when instead an error message is expected, one of the following approaches may be taken:
- Check the return value to see if it equals -1.
Use a conditional statement to check to see if the value is equal to -1. Then take appropriate action:
IDL> index = where(array eq value)
IDL> if (index[0] eq -1) then message,'No values found' |
- Check the "count" parameter value returned from the WHERE() function.
An optional "count" parameter can be given to WHERE() which will return the number of elements in the array that meet the criterion.
IDL> index = where(array eq value, count)
IDL> if (count eq 0) then message, 'No values found.' |
- Make use of the new /NULL keyword in IDL 8.0 to return a null value instead of a -1.
IDL 8.0 introduces the ability to define a null value. The behavior of the WHERE() function can be changed to return a null value, rather than a value of -1 if the /NULL keyword is used. For example:
IDL> index = where(array eq value, /null)
IDL> array[index] = 99 |
If a value of null is returned to index, then no action will be taken on the second line of code, the array will remain unaltered.
In addition, if it is necessary for the code to remain backward compatible with versions prior to 8.0, the /NULL keyword can be passed via the _EXTRA keyword structure, which will cause it to simply be ignored in IDL 7.1 and earlier.
IDL> index = where(array eq value, _extra={null:1})
IDL> array[index] = 99 |
This will ensure that in IDL 7.1 and earlier versions an error will be thrown as usual. In 8.0, again no action will be taken and no values in the array will be assigned the value of 99.