M provides indirection as a means to defer definition of elements of the code until run-time. Indirection names a variable that holds or "points" to the element. The indirection operator is the "at" symbol (@).
Most commands accept indirection of their entire argument.
GTM>set x="^INDER" GTM>do @x
This example is equivalent to
Any expratom or any local or global variable name may be replaced by indirection.
GTM>set x="HOOP",b="x" GTM>write a="HULA "__@b HULA HOOP GTM>
This example uses indirection within a concatenation operation.
Any element of an entryref may be replaced by indirection.
GTM>set lab="START",routine="PROG" GTM>do @lab^@routine
This example is equivalent to
A pattern code may be replaced by indirection.
GTM>FOR p="1U.20A1"",""1U.20A",5N IF x?@p QUIT GTM>ELSE WRITE !,"Incorrect format" QUIT
This example uses pattern code indirection to test x for either a name or a number.
Indirection may replace the prefix of a subscripted global or local variable name. This "name" indirection requires two indirection operators, a leading operator similar to the other forms of indirection, and a trailing operator marking the transition to those subscripts that are not specified by indirection.
GTM>SET from="B",to="^A(15),x="" GTM>FOR SET x=$O(@from@(x)) Q:x="" S @to@(x)=@from@(x)
This example uses name indirection to copy the level contents of a local array to a part of a global array. The example assumes that all existing first level nodes of variable B have data.
M indirection provides a very powerful tool for allowing program abstraction. However, because indirection is frequently unnecessary and has some disadvantages, use it carefully.
Because routines that use indirection in some ways do not contain adequate information for easy reading, such routines tend to be more difficult to debug and maintain.
To improve run-time performance, GT.M tends to move work from run-time to compile-time. Indirection forces compiler actions to occur at run-time, which minimizes the benefits of compilation.
M allows most forms of indirection to be recursive. However, in real applications, recursive indirection typically makes the code obscure and slow.
There are circumstances where indirection serves a worthwhile purpose. For instance, certain utility functions with a general nature may be clearly abstracted and coded using indirection. Because M has no "CASE" command, DO (or GOTO) with argument indirection provides a clear solution to the problem of providing complex branching.
Some M users prototype with indirection and then replace indirection with generated code that reduces run-time overhead. In any case, always consider whether indirection can be replaced with a clearer or more efficient approach.
Run-time errors from indirection or XECUTEs maintain $STATUS and $ZSTATUS related information and cause normal error handling but do not provide compiler supplied information on the location of any error within the code fragment.