Using Caché ObjectScript
Variables
[Home] [Back] [Next]
InterSystems: The power behind what matters   
Class Reference   
Search:    

A variable is the name of a location in which a value can be stored. Within ObjectScript, a variable does not have data type associated with it and you do not have to declare it.

Commonly, you use the SET command to define a variable by assigning it a value. You can assign a null string ("") value to a variable. Most commands and functions require a variable to be defined before it is used. If the variable is undefined, by default referencing it generates an <UNDEFINED> error. You can change Caché behavior to not generate an <UNDEFINED> error when referencing an undefined variable by setting the %SYSTEM.Process.Undefined() method.
You can use an undefined variable in some operations, such as the READ command, the $INCREMENT function, the $BIT function, and the two-argument form of the $GET function. These operations assign a value to the variable. The $DATA function can take an undefined or defined variable and returns its status.
Categories of Variables
Within ObjectScript, there are several kinds of variables, as follows:
Each of these is used for a specific purpose and may have different scoping rules. Within a program you can use any category of variable in the same way (such as assigning values or passing them as function arguments.)
Local Variables
A local variable is a variable that is stored within the current Caché process. It is accessible only to the process that created it. It is mapped to be accessible from all namespaces. When a process ends, all of the processes’ local variables are deleted.
Caché does not treat a SET or KILL of a local variable as a journaled transaction event; rolling back the transaction has no effect on these operations.
Naming Conventions
Define a local variable using the following naming conventions:
Note:
The %IS utility sets several local variables with all-uppercase names. These variable names should be avoided in situations where %IS is invoked. For further details, see I/O Devices and Commands in the Caché I/O Device Guide.
Invalid Names
A local variable name that does not follow the above naming conventions generates a <SYNTAX> error. There is one exception: if an invalid variable name begins with an underscore character followed by a letter, the system generates a <_CALLBACK SYNTAX> error. (Note the underscore character within the error name.) For example, SET _abc = 123 or SET x = _abc. This is because Caché identifies these names as VISM control names, rather than local variable names.
Types, Usage, and Scope
There are three kinds of local variables:
The XECUTE command can specify the variables it uses as either private or public. Refer to the section on Variable Declaration and Scope for more on public and private variables.
You can use the WRITE or ZWRITE command, with no arguments, to list all currently defined local variables. You can use the $QSUBSCRIPT function to return the components (name and subscripts) of a specified local variable, or the $QLENGTH function to return the number of subscript layers. You can use the KILL command to delete local variables.
Process-private Globals
A process-private global is a variable that is only accessible by the process that created it. It is mapped to be accessible from all namespaces. When the process ends, all of its process-private globals are deleted.
Process-private globals are intended to be used for large data values. They can serve, in many cases, as a replacement for the use of the Mgr/Temp directory, providing automatic cleanup at process termination.
Caché does not treat a SET or KILL of a process-private global as a journaled transaction event; rolling back the transaction has no effect on these operations.
Naming Conventions
A process-private global name takes one of the following forms:
^||name 
^|"^"|name 
^["^"]name 
^["^",""]name
These four prefix forms are equivalent, and all four refer to the same process-private global. The first form (^||name) is the most common, and the one recommended for new code. The second, third, and fourth forms are provided for compatibility with existing code that defines globals. They allow you to specify a variable that determines whether to define name as a process-private global or a standard global. This is shown in the following example:
  SET x=1       // toggle storage type
  IF x=1 {
    SET a="^"   // for a process-private global
  }
  ELSE {
    SET a=""    // for a standard global
  }
  SET ^|a|name="a value"
Process-private globals use the following naming conventions:
Listing Process-private Globals
You can use the ^GETPPGINFO utility to display the names of the current process-private globals and their space allocation, in blocks. ^GETPPGINFO does not list the subscripts or values for process-private globals. You can display process-private globals for a specific process by specifying its process Id (pid), or for all processes by specify the "*" wildcard string. You must be in the %SYS namespace to invoke ^GETPPGINFO.
The following example uses ^GETPPGINFO to list the process-private globals for all current processes:
  SET ^||flintstones(1)="Fred"
  SET ^||flintstones(2)="Wilma"
  ZNSPACE "%SYS"
  DO ^GETPPGINFO("*")
 
^GETPPGINFO has the following syntax:
^GETPPGINFO("pdf","options","outfile")
The pdf argument can be a process Id or the * wildcard. The options argument can be a string containing any combination of the following: b (return values in bytes), Mnn (return only those process-private variables that use nn or more blocks); S (suppress screen display; used with outfile); T (display process totals only). The outfile argument is the file path for a file in CSV (comma-separated values) format that will be used to receive ^GETPPGINFO output.
The following example writes process-private variables to an output file named ppgout. The S option suppresses screen display; the M500 option limits output to only process-private variables that use 500 or more blocks:
  ZNSPACE "%SYS"
  DO ^GETPPGINFO("*","SM500","/home/myspace/ppgout") 
Globals
A global is a special kind of variable that is automatically stored within the Caché database. It is mapped to a specific namespace, and can only be accessed within that namespace, unless an extended reference is used. A global can be accessed by any process. A global persists after the termination of the process that created it. It persists until explicitly deleted.
Caché treats a SET or KILL of a global as a journaled transaction event; rolling back the transaction reverses these operations. Locks may be used to prevent access by other processes to changes to a global until the transaction that made the changes has been committed. Refer to the Transaction Processing chapter for further details.
Within an ObjectScript program, you can use a global in the same way as any other variable. Syntactically, a global name is distinguished by a caret (“^”) character followed by a letter or a “%” character:
 SET mylocal = "This is a local variable"
 SET ^myglobal = "This is a global stored in the current namespace"
The naming conventions for globals are as follows:
Optionally, a global may specify an extended reference that defines its namespace or directory using a pair of vertical bars or square brackets immediately after the caret characters (for example: ^|"samples"|myglobal or ^|""|myglobal). These extended global references should not be confused with process-private globals.
You can use the $ZREFERENCE special variable to determine the name of the most recently used global. You can use the $QSUBSCRIPT function to return the components of a specified global, or the $QLENGTH function to return the number of subscript layers.
For much more information on globals, refer to Using Caché Globals.
Subscripted Variables
Local variables, process-private variables, and global variables can all take subscripts. The subscript conventions for all types of variables are similar:
Actual maximums depend on several factors. For further details on global maximums, refer to Global Structure chapter in Using Caché Globals.
Lock name subscripts follow the same conventions as variable subscripts.
Array Variables
An array variable is simply a variable with one or more subscript levels. Subscripts are enclosed in parentheses. Subscript levels are separated by commas. Any variable (with the exception of special variables) can be used as an array, as shown in the following example:
 SET a(1) = "A local variable array"
 SET a(1,1,1) = "Another local variable array"
 SET ^||a(1) = "A process-private global array"
 SET ^a(1) = "A global array"
 SET obj.a(1) = "A multidimensional array property"
For local variables, the maximum number of subscript levels is 255. For global variables, the maximum number of subscript levels depends on the length of the subscript names. For subscript conventions and limits, refer to the Global Structure chapter in Using Caché Globals.
Special Variables
ObjectScript includes a number of built-in special variables (also referred to as system variables) that are used to make certain system information available to applications. All special variables are supplied with Caché and are named with a “$” character prefix. Users cannot define additional special variables. The set of special variables is mapped to be accessible from all namespaces.
The value of a special variable is set to the current state of some aspect of your operating environment. Some special variables are initially set to the null string (""); referencing a special variable should never generate an <UNDEFINED> error. The value of a special variable is specific to the current process and cannot be accessed from another process.
Users can set some special variables with the SET command; other special variables are not user-modifiable. Refer to the individual special variables for further details.
The following example uses the special variable $HOROLOG:
 SET starttime = $HOROLOG
 HANG 5
 WRITE !,$ZDATETIME(starttime)
 WRITE !,$ZDATETIME($HOROLOG)
 
The special variable $HOROLOG stores the current system date and time. The SET command uses this special variable to set the user-defined local variable starttime to this value. The HANG command then suspends the program for 5 seconds. Finally, the two $ZDATETIME functions return starttime and the current system date and time in a user-readable format.
Other examples of special variables include:
 WRITE !,"$JOB = ",$JOB   // Current process ID
 WRITE !,"$ZVERSION = ",$ZVERSION   // Version info
 
Many special variables are read-only; they cannot be set using the SET command. Other special variables, such as $DEVICE, are read-write, and can be set using the SET command.
Special variables cannot take subscripts. Special variables cannot be incremented using the $INCREMENT function or killed using the KILL command. Special variables can be displayed using the WRITE, ZWRITE, ZZWRITE, or ZZDUMP commands, as described in Display (Write) Commands in the “Commands” chapter of Using Caché ObjectScript.
Refer to the Caché ObjectScript Reference for a list and detailed descriptions of the special variables.
Object Properties
An object property is a value associated with, and stored within, a specific instance of an object. Strictly speaking, an object property is not a variable, but syntactically you can use an object property in exactly the same way as any other local variable.
There are several types of property references: oref.property, ..property, and i%property. The object reference (oref) must be a local variable, not an expression. The property reference can reference a single-value property or a subscripted multidimensional property. There can be chained property references like oref.prop1.prop2.
The following example shows a property reference used as a variable:
  // Create an Address object
  SET address = ##class(Sample.Address).%New()
  // Use the properties of the object
  SET address.City = "Boston"
  WRITE "City: ",address.City,!
 
There are some limitations for the use of property references as variables. A property of any type cannot be modified using SET $BIT() or SET $LISTBUILD(); a non-multidimensional property cannot be modified using SET $EXTRACT(), SET $LIST(), or SET $PIECE(). $DATA(), $GET(), and $INCREMENT() can only take a property if the property is multidimensional. Properties cannot be used with the MERGE command. These operations can be done within an object method using the special instance variable syntax i%PropertyName.
Variable Typing and Conversion
Variables in ObjectScript are untyped — there are no specified data types. (This is also true of JavaScript, VBScript, and Caché Basic.) This means that you can assign a string value to a variable and, later on, assign a numeric value to the same variable. As an optimization, Caché may use different internal representations for strings, integers, numbers, and objects, but this is not visible to the application programmer. Caché automatically converts (or interprets) the value of a variable, based on the context in which it is used.
Some examples:
 // set some variables
 SET a = "This is a string"
 SET b = "3 little pigs"
 SET int = 22
 SET num = 2.2
 SET obj = ##class(Sample.Person).%New()

 // Display them
 WRITE "Here are the variables themselves: ",!
 WRITE "a: ",a,!
 WRITE "b: ",b,!
 WRITE "int: ",int,!
 WRITE "num: ",num,!
 WRITE "obj: ",obj,!,!

 // Now use them as other "types"
 WRITE "Here are the numeric interpretation of",!
 WRITE "a, b, and obj: ",!
 WRITE "+a: ",+a,!
 WRITE "+b: ",+b,!
 WRITE "+obj: ",+obj,!,!
 
 WRITE "Here are concatenations of int and num:",!
 WRITE "Concatenating int: ","I found " _ int _ " apples.",!
 WRITE "Concatenating num: ","There are " _ num _ " pounds per kilogram.",!
 
Caché converts values as follows:
ObjectScript Type Conversion Rules
From To Rules
Number String A string of characters that represents the numeric value is used, such as 2.2 for the variable num in the previous example.
String Number Leading characters of the string are interpreted as a numeric literal, as described in the String-to-Number Conversion section of the “Operators and Expressions” chapter. For example, “–1.20abc” is interpreted as -1.2 and “abc123” is interpreted as 0.
Object Number The internal object instance number of the given object reference is used. The value is an integer.
Object String A string of the form n@cls is used, where n is the internal object instance number and cls is the class name of the given object.
Number Object Not allowed.
String Object Not allowed.
Object Values
An object value refers to an instance of an in-memory object. You can assign an object value to any local variable:
 SET person = ##class(Sample.Person).%New()
 WRITE person,!
 
Note:
The value of person is that of an object reference (OREF) converted into a string. This string or its value cannot be used to load an object from the database.
You can refer to the methods and properties of an object using dot syntax:
 SET person.Name = "El Vez"
You can determine if a variable contains an object using the $ISOBJECT function:
 SET str = "A string"
 SET person = ##class(Sample.Person).%New()

 WRITE "Is string an object? ", $IsObject(str),!
 WRITE "Is person an object? ", $IsObject(person),!
 
You cannot assign an object value to a global. Doing so will result in a runtime error.
Assigning an object value to a variable (or object property) has the side effect of incrementing the object’s internal reference count. When the number of references to an object reaches 0, Caché will automatically destroy the object (invoke its %OnClose method and remove it from memory). For example:
 SET person = ##class(Sample.Person).%New() // one reference to Person
 SET alias = person // two references

 SET person = "" // 1 reference 
 
 SET alias = "" // no references left, object destroyed
Variable Declaration and Scope
Unlike other languages, you do not declare variables in ObjectScript.
Variable scoping determines when a variable is “visible” to a program. In ObjectScript, there are two sets of rules for variable scoping:
These mechanisms are described in greater detail in the User-defined Code chapter.
Using #Dim
When writing code in Studio, you can use the #Dim preprocessor directive. #Dim provides information on the intended type of a variable. Studio uses this information for code completion with the Studio Assist feature. This information can also be used for documentation or to provide information to others who may view the code. (For more information on Studio Assist, see the section Editor Options in the “Setting Studio Options” chapter of Using Studio.)
The syntax forms of #Dim are:
#Dim VariableName As DataTypeName
#Dim VariableName As List Of DataTypeName
#Dim VariableName As Array Of DataTypeName
where VariableName is the variable for which you are naming a data type and DataTypeName specifies that data type. Studio provides a menu from which you can select the DataTypeName value.
#Dim also allows you to specify an initial value for a variable, as in the following:
#Dim President As %String = "Obama"