Alias variables provide a layer of abstraction between the name of a local variable and an array analogous to that provided by M pass by reference in routines and function calls. Multiple local variables can be aliased to the same array, and a SET or KILL to one acts as a SET or KILL to all. Alias container variables provide a way using a subscripted local to store a reference to an entire local variable array, which protects the associated array even when it's not accessible through any current local variable name.

GT.M aliases provide low level facilities on which an application can implement object-oriented techniques. An object can be mapped onto, and stored and manipulated in an array, then saved in an alias container variable whence it can be retrieved for processing. The use of appropriate subscripts in the array used for a container, provides a way to organize the stored objects and retrieve them by using the $ORDER() function to traverse the container array. The use of alias variables to implement objects provides significant efficiencies over traditional local variables because alias variables and alias container variables eliminate the need to execute MERGE commands to move objects.

Example:

GTM>kill A,B
        
GTM>set A=1,*B=A ; B & A are aliases
GTM>write B
1
GTM> 

Within the context of Alias Variables extensions:

The following table summarizes Alias Variables extensions.

GT.M Extensions for Alias Variables

EXTENSION

EXPLANATION

Set *

Explicitly creates an alias. For more information, refer to the description of SET * in a??Seta??

Kill *

Removes the association between its arguments, and any associated data cells. For more information, refer to the description of KILL * in a??Killa??

Quit *

When QUIT * terminates an extrinsic function or an extrinsic special variable, it always returns an alias container. For more information, refer to the description of QUIT * in a??Quita??.

ZWrite / ZSHow "V"

Produces Alias Variables format output. For more information, refer to a??ZWRITE Format for Alias Variablesa??

New

For the scope of the NEW, a NEW of a name suspends its alias association. For more information, refer to a??Newa??.

Exclusive New

Create a scope in which some associations between an lname or an lvn and an array may be invisible. For more information, refer to a??Newa??.

$ZAHandle()

returns a unique identifier (handle) for the array associated with an lname or an alias container; for an subscripted lvn that is not an alias container, it returns an empty string. For more information, refer to a??$ZAHandle()a??

$ZDATA()

Extends $DATA() to reflect the current alias state of the lvn or lname argument in order to identify alias and alias container variables. For more information, refer to a??$ZDATA()a??.

View and $View()

  • VIEW provides LV_GCOL, LV_REHASH, and STP_GCOL to perform garbage collection and local variable lookup table reorganization operations which normally happen automatically at appropriate times. For more information on the keywords of the VIEW command, refer to a??Key Words in VIEW Commanda??.

  • $VIEW() provides LV_CREF, LV_GCOL, and LV_REF. FIS uses the LC_CREF, LV_GCOL, LV_REF keywords in testing and is documenting them to ensure completeness in product documentation. They may (or may not) be useful during application development for debugging or performance testing implementation alternatives. For more information the keywords of $VIEW(), refer to a??Argument Keywords of $VIEW()a??.

TSTART, RESTART, and ROLLBACK

TSTART command can optionally list names whose arrays are restored on a transaction RESTART. If any of these are alias variables or have nodes which are alias container variables, their associations are also restored on transaction RESTART. For more information, refer to ChapterA 6: a??Commandsa??.

Alias Variables provide access to an array through multiple names. Conceptually an alias variable is the same as a pass-by-reference joining of multiple variable names, except that the joining of alias variables is explicit, whereas that of variables passed by reference is implicit. Indeed, the underlying implementation of alias variables and pass-by-reference within GT.M is the same.

The following table show the type of data movement of alias and alias container variables from QUIT * in a function to a SET * target:

QUIT *

SET *

Result

ZWRITE

set *a=$$makealias(.c)

Creates an alias container

Dereferences the alias container

Same as set *a=c

*c=a

set *a(1)=$$makealias(.c)

Creates an alias container

Dereferences the alias container

Same as set *a(1)=c

*a(1)=c

set *a=$$makecntnr(.c)

Returns an alias container

Copies the alias container

Same as set *a=c(1)

*c=a

set *a(1)=$$makecntnr(.c)

Returns an alias container

Copies the alias container

Same as set *a(1)=c(1)

*a(1)=c

The makealias function returns an alias of the argument:

makealias(var)
 quit *var

The makecntr function returns an alias container of the argument:

makecntnr(var)
 new cont
 set *cont(1)=var
 quit *cont(1)

Example

GTM>Set A=1,*B=A ; Create an array and an association
                
GTM>ZWRite ; Show that the array and association exist
A=1 ;*
*B=A
GTM>Kill *A ; Remove the association for A - it now has no association and no array
GTM>ZWRite ; B is a traditional local variable
B=1
Example:
GTM>Set A=2 ; add a value for A
                
GTM>ZWRite ; A and B have different values and both are traditional local variables
A=2
B=1
GTM>

KILL on the other hand, removes data in the array (and possibly the array itself) without affecting any alias association.

GTM>Set A=2,*B=A ; Create an array and an association
                
GTM>ZWRite ; Both array and association exist
A=2 ;*
*B=A
GTM>Kill A ; Kill the array
GTM>ZWRite ; There's no data to show - only the association
*B=A
GTM>Set B=3 ; Create a new value
GTM>ZWRite ; The association was unaffected by the Kill
A=3 ;*
*B=A
GTM>

Example:

$ /usr/lib/fis-gtm/V5.4-002B_x86/gtm -run ^killalias
killalias ; Demonstrate Kill * of pass-by-reference
       ZPrint ; Print this program
       Set A=1,C=3
       Write "------------",!
       Write "Initial Values:",!
       ZWRite
       Do K1(.A,.C) ; Pass A & C by reference
       Write "------------",!
       Write "Value of A is unchanged because of Kill *B, but C has changed: ",!
       ZWRite
       Quit
;
K1(B,D) ; A & C are bound to B & D respectively
       Write "------------",!
       Write "A & B are aliases, as are C & D:",!
       ZWRite
       Kill *B
       Set B=2,D=4
       Write "------------",!
       Write "After Kill *B, A & B are different but C & D remain associated:",!
       ZWrite
       Quit
------------
Initial Values:
A=1
C=3
------------
A & B are aliases, as are C & D:
A=1 ;*
*B=A
C=3 ;*
*D=C
------------
After Kill *B, A & B are different but C & D remain associated:
A=1
B=2
C=4 ;*
*D=C
------------
Value of A is unchanged because of Kill *B, but C has changed: 
A=1
C=4
Example:
GTM>Set A=1,*B=A ; Create an array and association
GTM>ZWRite ; Verify that it's there
A=1 ;*
*B=A
GTM>Kill (A) ; Kill everything except A
GTM>ZWRite ; Demonstrate that A also has no array
GTM>Set A=2 ; Create an array
GTM>ZWRite ; The association survived the Kill
A=2 ;*
*B=A
GTM>

Example:

$ /usr/lib/fis-gtm/V5.4-002B/gtm -run ^tprestart
tprestart ; Transaction restart variable association also restored on restart
  zprint ; Print this program
  set A="Malvern",C="Pennsylvania",E="USA"
  set *B=C,*D(19355)=E
  write "------------",!
  write "Initial values & association",!
  zwrite
  tstart (B,D) ; On restart: A not restored, B,D restored, C,E restored by association
  if '$TRestart Do  ; Change C,E if first time through
  .set C="Wales",E="UK"
  .kill *D(19355)
  .write "------------",!
  .write "First time through transaction; B,C,D,E changed",!
  .zwrite
  .set A="Brynmawr"
  .kill *B
  .write "------------",!
  .write "A changed; association between B & C and D & E killed; B,D have no value",!
  .zwrite
  .trestart
  else  Do  ; Show restored values on restart
  write "------------",!
  write "Second time through transaction; B,C,D,E & association restored",!
  zwrite
  tcommit ; No global updates in this transaction!
  quit
------------
Initial values & association
A="Malvern"
B="Pennsylvania" ;*
*C=B
*D(19355)=E
E="USA" ;*
------------
First time through transaction; B,C,D,E changed
A="Malvern"
B="Wales" ;*
*C=B
E="UK" ;*
------------
A changed; association between B & C and D & E killed; B,D have no value
A="Brynmawr"
C="Wales" ;*
E="UK" ;*
------------
Second time through transaction; B,C,D,E & association restored
A="Brynmawr"
B="Pennsylvania" ;*
*C=B
*D(19355)=E
E="USA" ;*

Note that TROLLBACK does not restore alias variables:

/usr/lib/fis-gtm/V5.4-002B_x86/gtm -run ^tprollback
tprollback ;
  zprint ; Print this program
  set A(1)=1,A(2)=2,A(3)=3
  set B(1)="1b",*B(2)=A,B(3)=3 ; B includes a container for A
  set *C(1)=B   ; C includes a container for B
  kill *A,*B   ; C is the only way to the data
  write "------------",!
  write "Only containers before transaction:",!
  zwrite
  tstart (C)
  if '$trestart
  .set *D=C(1) ; D is now an alias for what used to be B
  .set D(3)=-D(3)
  .set *D=D(2) ; D is now an alias for what used to be A
  .set D(1)=-D(1)
  .kill *D  ; Kill D after is used to manipulate the arrays
  .write "------------",!
  .write "Changed values before restart:",!
  .zwrite
  .trestart
  write "------------",!
  write "Restored values restart:",!
  zwrite
  kill C ; Kill only handle to arrays
  write "------------",!
  write "No local arrays left:",!
  zwrite
  trollback  ; Rollback transaction, don't commit it
  write "------------",!
  write "Rollback doesnt restore names and local arrays",!
  zwrite
  quit
------------
Only containers before transaction:
$ZWRTAC=""
*C(1)=$ZWRTAC1
$ZWRTAC1(1)="1b"
*$ZWRTAC1(2)=$ZWRTAC2
$ZWRTAC2(1)=1
$ZWRTAC2(2)=2
$ZWRTAC2(3)=3
$ZWRTAC1(3)=3
$ZWRTAC=""
------------
Restored values restart:
$ZWRTAC=""
*C(1)=$ZWRTAC1
$ZWRTAC1(1)="1b"
*$ZWRTAC1(2)=$ZWRTAC2
$ZWRTAC2(1)=1
$ZWRTAC2(2)=2
$ZWRTAC2(3)=3
$ZWRTAC1(3)=3
$ZWRTAC=""
------------
No local arrays left:
------------
Rollback doesnt restore names and local arrays

Example:

$ /usr/lib/fis-gtm/V5.4-002B_x86/gtm -run ^aliasexample; Extended annotated alias example
    zprint
    write "------------",!
    set x="name level",x(1)=1,x(1,2)="1,2",x("foo")="bar"
    write $ZDATA(x),! ; x is a conventional lvn - output 11
    set *y=x ; x an y are now alias variables
    write $ZDATA(x),! ; output appears as 111
    set *a(1)=y ; a(1) is now an alias container variable
    set b="bness",b("b")="bbness" ; b is a conventional lvn
    set *b=a(1) ; b joins x and y as alias variables for the same data
    ; prior b values are lost
    ; set *<name> is equivalent to Kill *<name> Set *<name>
    set y("hi")="sailor" ; Assignment applies to all of {b,x,y}
    kill b("foo") ; Kill applies to all of {b,x,y}
    kill *x ; x is undefined and no longer an alias variable
    ; b and y still provide access to the data
    write a(1),"<",! ; output appears as <
    write a(1)*3,! ; output appears as 0
    write $length(a(1)),! ; output appears as 0
    set c=y,c("legs")="tars" ; c is conventional lvn with value "name level"
    do sub1
    write $Data(c),! ; output is 1
    do sub2(.c)
    set a(1)="" ; a(1) ceases to be an alias container variable
    ; has the value ""
    write $D(i),! ; output is 0
    kill *c,*y ; c and y become undefined lvns
    zwrite b ; output is b("got")="a match"
    ; it's no longer an alias variable
    ; as everything else has gone
    quit
sub1
    new y ; in this scope y is no longer an alias for b
    set *y=c ; in this scope c and y are alias variables
    kill y("legs") ; Kill apples to all of {c,y}
    kill *y ; in this scope y is no longer an alias for c
    ; this is really redundant as
    ; the Quit implicitly does the same thing
    quit
sub2(i) ; i and c are joined due to pass-by-reference
    write $ZAHandle(c)=$ZAHandle(i),! ; output appears as 1
    kill b ; data for {b,y} is gone
    ; both are undefined, but remain alias variables
    set *c=a(1) ; c joins {b,y} as alias variable; prior value of c lost
    ; c is no longer alias of i
    write $ZAHandle(c)=$ZAHandle(i),! ; output appears as 0
    set i=a(1) ; Assignment applies to i - value is ""
    wet c("got")="a match" ; Assignment applies to all of {b,c,y)
    quit
 
------------
11
111
<
0
0
1
1
0
0
b("got")="a match"
loading table of contents...