Checking for Keywords
QUESTION: How can I tell if a keyword was used in my program?
ANSWER: Despite what your colleague may have told you, or what you believe you read in the IDL documentation, it is NOT possible to reliably determine if a keyword was used in a call to your program. (Click here for a definition of NOT possible.)
What you may be able to determine reliably is whether the variable that holds the value of the keyword in your program is defined or not. This is similar to knowing whether it was used or not, but not exactly the same, as many an IDL programmer has discovered too late.
There are three functions that can be used to check keyword parameters: N_Elements, Keyword_Set, and Arg_Present. They are all, unfortunately, mis-named when it comes to indicating how they work, resulting in great confusion in IDL programs. In fact, with the possible exception of writing a loop where an array operation would do, nothing is more badly mangled in IDL programs than the correct way to check keywords. Here is how it should be done.
First of all, there is a distinction to be made in the definition of a keyword between the name of the keyword and the variable that holds the value of the keyword in the program. The name of the keyword is aways on the left. The variable that holds that value of the keyword is always on the right. This is true whether the keyword is an input or an output keyword.
PRO JUNK, KeywordName=keywordValue
There is nothing that says that the name of the keyword and the variable that holds the value in the program has to be the same, but people who make them different, I've found, have a lot more trouble keeping things straight than people who give them the same name. Just an observation. I almost always define my keywords like this:
PRO JUNK, Data=data
What you are going to check in your program is the variable that holds the value of the keyword. The keyword name is what people are going to use when they call the program with the keyword:
IDL> junk, Data=[3,5,4,6,9,10]
Now, in this case, we are going to use the variable data somewhere in our code. Perhaps we are going to use it like this:
Clearly, we have to make sure the data variable is defined before we use it or this line of code will not execute.
Is a Keyword Defined?
We find out whether the variable is defined or not by using the N_Elements function. This function returns a zero if its argument is undefined. So we check the data keyword like this. If it is undefined, we will define it as an 11-element vector.
IF N_Elements(data) EQ 0 THEN data = Findgen(11)
With only a couple of exceptions, it is necessary to test every keyword you define like this. If you don't, you are going to find yourself creating required keywords, which will defeat the very purpose of keywords.
Checking Binary Keywords
There is a class of keywords that generally are not checked with the N_Elements function. These are keywords that have a binary meaning. In other words the keyword is on/off, true/false, yes/no, 1/0, etc. These keywords are more like a flag. For example, you might define a NOERASE keyword, like this:
PRO JUNK, Data=data, NoErase=noerase
If this keyword is set, you don't want to erase the display when you execute the Plot command. If it is not set, you want the Plot command to erase the display as normal. We check these keywords with the function Keyword_Set. This function returns a 0 if its argument is 0 or undefined. It returns a 1 if its argument is anything besides 0 or 1. So, for example, you might see code like this:
noEraseFlag = Keyword_Set(noerase) ... Plot, data, NoErase=noEraseFlag
More often, you see the Keyword_Set function used in the code directly. For example, like this:
Plot, data, NoErase=Keyword_Set(noerase)
I see Keyword_Set used for all kinds of things in code that I am asked to look at. But if it is not being used to check the value of a binary-type keyword, it is being used in that code incorrectly. Sooner or later that code will fail. Usually, when you try to set the value of the keyword to zero.
Beware the Misnamed Arg_Present
More rarely I see people misusing the terribly misnamed function Arg_Present. This function does not tell you if a keyword argument is present or not. It does tell you whether the keyword that is present is a keyword that has been passed by reference (Arg_Present returns a 1) or is a keyword that has been passed by value (Arg_Present returns a 0).
The purpose of this function is to check to see if an output variable can be passed back to the user of the keyword. In other words, suppose I wanted to calculate the FFT of a large image and pass the resulting complex image back to the user via a ComplexImage keyword. I really wouldn't want to go to the trouble of doing this unless that user asked for it and provided a variable to hold the result. I might write code like this:
PRO JUNKER, ComplexImage=compleximage ... IF Arg_Present(compleximage) THEN compleximage = FFT(image, -1)
The IF statement would be executed if I called the Junker command like this:
IDL> junker, ComplexImage=cimage
But not if I called it like this, since a subscripted array is passed by value and not by reference. Hence, the Arg_Present function will return a 0 even though an argument is present in this circumstance.
IDL> junker, ComplexImage=cimage
Does "Not Possible" Mean "Impossible"?
In the very first paragraph of this article I wrote this:
"Despite what your colleague may have told you, or what you
believe you read in the IDL documentation, it is NOT possible
to reliably determine if a keyword was used in a call to your program."
Is this really true? Well, yes, most of the time. :-)
It is certainly true if what you mean by it is that you use any one of the three routines described above as advertised by RSI. But software is software, and you are suppose to be able to do anything if you are clever enough. J.D. Smith of Cornell University is clever enough, and here is a tiny function he wrote that can reliably tell you whether your keyword was used or not.
pro testme, KEY=k if n_elements(k) ne 0 OR arg_present(k) then $ print,'You used KEY!' else $ print,'You neglected KEY!' end
I'll leave it as an exercise for the user to determine if it is worth the trouble to check your keywords like this. :-)
Copyright © 1997-1999 David W. Fanning
Last Updated 30 June 1999