The SCOPE_VARNAME function returns the names of variables outside the local scope of the currently running procedure or function. Given a variable within the local scope of the currently running routine, SCOPE_VARNAME can supply the name under which it is known in an earlier routine in the current chain of active routines. Similarly, given the positional index of a common block variable, SCOPE_VARNAME can report the name that the variable was given in the routine that first defined that common block within the current IDL session.
In normal IDL operation, routines are not allowed to see variables outside their own scope. This restriction is a fundamental and important property of structured modular programming. Code that accesses non-local scope to alter variables within other active routines can quickly become extremely difficult to understand and maintain. For this reason, avoid using the IDL scope routines.
Despite this warning, there is an important class of application that requires the functionality provided by these routines. Programs, usually with graphical user interfaces, that import and export data from the callers’ scope need to be able to access the user’s data variables directly, and without requiring them to explicitly pass those variables to the application as parameters. The SCOPE_VARFETCH function is used to access those variables, and SCOPE_VARNAME is used to obtain the correct names with which to refer to them. SCOPE_LEVEL returns the scope level of the currently executing routine. The IDL iTools and the ENVI image processing software are examples of programs that need to be able to perform these operations.
Note: For more information, see Interpreter Frames, Level, and Variable Scope.
The value returned by SCOPE_VARNAME depends on whether or not the COMMON keyword is set, and whether or not plain arguments are provided in the call. In all cases, the result is of a scalar string or a string array of variable names.
COMMON Keyword Not Set
The result is a string array, with each element giving the name of the corresponding argument variable within the scope of the routine specified by the LEVEL keyword. If an argument does not exist within the target scope, a scalar null string is returned.
Arguments Not Present
The result is a string array containing the names of all known variables within the scope of the routine specified by the LEVEL keyword. If the specified scope has no variables, a scalar null string is returned.
See the description of the LEVEL keyword for additional information.
COMMON Keyword Set
Each argument supplies the positional index of a variable within the common block. The result is a string array, with each element giving the name of the corresponding variable with that index within that common block.
Arguments Not Present
The result is a string array containing the names of all known variables defined within a specified common block, given in the order in which they exist in the block.
If the COMMON keyword is set, the arguments to SCOPE_VARNAME are integers, giving the positional index of variables within the specified common block for which names are to be returned.
Set this keyword to a string containing the name of a common block to cause SCOPE_VARNAME to return the names of variables contained within the specified block. If COMMON is set, the arguments to SCOPE_VARNAME are integers that give the positional index of variables within the specified common block for which names are to be returned.
Note: See COMMON Variable Names for more information on the names returned.
The COMMON keyword cannot be used in conjunction with the LEVEL keyword.
Set this keyword to a named variable that will contain the number of elements returned in the array value returned by SCOPE_VARNAME. If SCOPE_VARNAME returns a null string, a 0 is returned. This circumstance will occur if there are no arguments, the COMMON keyword is not set, and the specified scope has no variables.
Set this keyword to an integer that specifies the scope within which the desired variable should be found. The level can be either an absolute value or relative to the current scope, as shown in the following table:
Level 0 always refers to the frame for the currently executing routine. This is the default value.
Negative levels are a relative specification and refer to the frames of active routines relative to the currently executing routine. Level -1 is the direct caller of the current routine, -2 is the caller of the caller of the current routine, and so forth. If you specify a level that is deeper than the current call stack, SCOPE_VARNAME clips the value not to go past $MAIN$.
Positive levels are an absolute specification and refer directly to the specified frame. Level 1 is $MAIN$, level 2 is the routine called from $MAIN$, and so forth. If you specify a level that is past the currently executing routine, SCOPE_VARNAME clips the value to the level of the current routine.
The LEVEL keyword cannot be used in conjunction with the COMMON keyword.
Variables in IDL common blocks do not actually have names. Rather, IDL represents common blocks internally as an array of variables, and these variables are referenced by their positional index. Hence, the first variable is at position 0, the second at position 1, and so forth. When you specify a COMMON declaration in an IDL routine, you specify names to be used for these variables within the scope of that routine. In fact, different routines are allowed to use entirely different names to refer to a given variable. However, this can quickly become confusing, and most programmers use the same names in every case.
The first routine in which a COMMON block is defined is remembered by IDL as part of the state of that block. When another routine defines the same common block, it is allowed to omit the variable names. In this case, IDL uses the same names used in the original defining routine.
When the COMMON keyword is specified to the SCOPE_VARNAME function, the names returned are the names that were defined by the originally defining routine. Because good programming practice dictates that the same names be used everywhere, this result usually causes no confusion. However, in an environment where different names are in use in different scopes, you should be aware of the difference. For example, execute the following COMMON statement at the IDL prompt:
COMMON DOGS, poodle, spaniel, retriever
Now execute the following IDL routine:
COMMON DOGS, breed1, breed2, breed3
PRINT, 'In this scope: ', SCOPE_VARNAME(breed1, breed2, breed3)
PRINT, 'In $MAIN$: ', SCOPE_VARNAME(breed1, breed2, breed3, $
PRINT, 'In COMMON: ', SCOPE_VARNAME(COMMON='dogs', 0, 1, 2)
The following output is produced when procedure DOGS is called:
In this scope: BREED1 BREED2 BREED3
In $MAIN$: POODLE SPANIEL RETRIEVER
In COMMON: POODLE SPANIEL RETRIEVER
If you do not specify the COMMON keyword, SCOPE_VARNAME translates the names of all variables, common or regular, relative to the specified scope. Hence, the variables in the DOGS common block appear as POODLE, SPANIEL, and RETRIEVER in $MAIN$, and as BREED1, BREED2, and BREED3 within procedure DOGS, despite the fact that they refer to the same variables. When you direct SCOPE_VARNAME to work from the common block instead of from an interpreter frame, the function uses the names from the scope of the routine that defined the common block, which in this example is $MAIN$.
Following this advice can minimize confusion:
- Use the same names for common block variables in all definitions. A convenient way to do so is to take advantage of the abbreviated form of the COMMON declaration, in which second and following declarations can leave off the variable names, and IDL will substitute the names from the initial definition.
- When possible, routines that use SCOPE_VARNAME should not specify the COMMON keyword. Instead, translate their names relative to the caller’s scope.
The following procedure outputs the names of all variables currently defined in the IDL main program, $MAIN$. It also prints the name of its argument, in its own scope, in that of its caller, and in that of $MAIN$.
PRO test_scope_varname, arg
PRINT, 'All variables in $MAIN$: ', SCOPE_VARNAME(LEVEL=1)
PRINT, 'Argument name in local scope: ', SCOPE_VARNAME(arg)
PRINT, 'Argument name in caller scope: ', SCOPE_VARNAME(arg, $
PRINT, 'Argument name in $MAIN$ scope: ', SCOPE_VARNAME(arg, $