Variables
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 referenced. If the variable is undefined, by default referencing it generates an <UNDEFINED> error. You can change InterSystems IRIS® data platform behavior to not generate an <UNDEFINED> error when referencing an undefined variable by setting the %SYSTEM.Process.Undefined()Opens in a new tab 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.
Unlike many computer languages, ObjectScript does not require variables to be declared. A variable is created when it is assigned a value. ObjectScript is a “typeless” language; a variable can receive data of any type. See Variable Declaration and Variable Typing and Conversion.
Categories of Variables
Within ObjectScript, there are several kinds of variables, as follows:
-
Global variables or globals
-
Process-private global variables or PPGs
-
i%property instance variables (discussed on another page)
-
Special variables or system variables
Local Variables
A local variable is a variable that is available in memory within the current InterSystems IRIS process. It is accessible only to the process that created it. It is accessible from all namespaces; that is, if the process changes namespaces, the variable is still available. When a process ends, all of its local variables are deleted.
Naming Conventions
Rules and Guidelines for Identifiers provides all the details, but briefly:
-
For a local variable name, the first character must be either a letter or the percent (%) character.
Variable names starting with the % character are known as “percent variables” and have different scoping rules. In your code, for a local percent variable, start the name with %Z or %z; other names are reserved for system use.
-
All variable names are case-sensitive, and this includes local variable names. For example: MYVAR, MyVar, and myvar are three different local variables.
-
Local variable names must be unique for the current process. Other processes may have local variables with the same name.
-
A process-private global or a global may have the same (apparent) name as a local variable. For example: myvar, ^||myvar, and ^myvar are three different variables.
-
Local variables can take subscripts. See Rules About Subscripts.
A local variable name that does not follow the rules generates a <SYNTAX> error. There is one exception: if an attempted variable name begins with an underscore character followed by a letter, the system generates a <_CALLBACK SYNTAX> error. For example, SET x=_a.
Scope of Local Variables
In ObjectScript code, all local variables are public, and can thus be accessed by any operation executed by that process in the current context. Access to a local variable value is restricted as follows:
-
The NEW command creates a new local variable context. An argumentless NEW creates a new context in which none on the existing local variables are defined. NEW var creates a new context in which the local variable var is not defined. The QUIT command reverts to the prior local variable context.
-
Within a procedure block local variables are private by default. A private local variable is only defined within that procedure block.
Local variables within a procedure block behave as follows:
-
Private variables. A local variable used within a procedure block is a private variable and is only defined within that procedure block, unless it is declared a public variable or it is a % variable. You cannot use the NEW command on a private variable in a procedure block.
-
Public variables. A procedure block can explicitly declare a list of local variables as public variables. These variables values are accessible outside the procedure block. This comma-separated list of public variables can include non-existent variables and % variables. You can use the NEW command on a public variable in a procedure block.
A public variables list for the two local variables var1 and var2 is specified as follows: MyProc(x,y) [var1,var2] PUBLIC { code body }. (Note that the PUBLIC keyword specifies that the procedure is public; it has nothing to do with the public variables list.) Public variables are specified as a comma-separated list. Only unsubscripted local variables can be specified; specifying an unsubscripted variable in the public variables lists makes all of its subscript levels public as well. Only a simple object reference (OREF) can be specified; specifying an OREF in the public variables lists makes all of its object properties public as well. The list of public variables can include undefined variables.
-
% Variables. A local variable whose name starts with “%” is automatically declared a public variable. This makes it possible to define variables that are visible to all code within a process without having to explicitly list these variables as public. Only variables that begin with “%Z” or “%z” are available for application code; all other % variables are reserved for system use according to the rules described in Rules and Guidelines for Identifiers. You can use the NEW command on a % variable in a procedure block.
These mechanisms are described in greater detail in Procedure Variables.
-
-
The XECUTE command defines local variables as public by default. You can explicitly define a local variable as private within the XECUTE command. Refer to XECUTE for more on explicitly defining local variables as either private or public.
You can use the WRITE or ZWRITE command, with no arguments, to list all currently defined local variables. You can use the KILL command to delete local variables.
Globals
A global is a special kind of variable that is automatically stored within the InterSystems IRIS 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.
Within ObjectScript code, you can use a global in the same way as any other variable. Syntactically, a global name is distinguished by an initial caret (^) character:
SET mylocal = "This is a local variable"
SET ^myglobal = "This is a global stored in the current namespace"
For complete information on names, see Rules and Guidelines for Identifiers. Briefly:
-
The first character after the caret must be either a letter or the percent (%) character.
Global names starting with ^% are known as “percent variables” and are available in all namespaces. In your code, for these variables, start the name with ^%Z or ^%z; other names are reserved for system use.
-
The second and subsequent characters of a global name may be letters, numbers, or the period character. A period cannot be used as the first or last character of the name.
-
Unlike local variables, no global name can contain Unicode letters — letter characters above ASCII 255. Attempting to include a Unicode letter in a global name results in a <WIDE CHAR> error.
-
Global names are case-sensitive.
-
A global name must be unique within its namespace.
-
Global names are limited to 31 characters, exclusive of the prefix characters. You may specify a name longer than 31 characters, but only the first 31 characters are used. Therefore, a global name must be unique within its first 31 characters.
-
Like other variables, globals can take subscripts. See Rules About Subscripts.
-
Some global names are reserved for InterSystems use. See Global Variable Names to Avoid.
It is possible to use an extended reference to refer to a global in another namespace. The syntax uses a pair of vertical bars or square brackets immediately after the caret characters (for example: ^|"samples"|myglobal or ^|""|myglobal). These syntaxes should not be confused with process-private globals.
For more information on globals, refer to Using Globals.
Process-Private Globals
A process-private global is a variable that is only accessible by the process that created it. When the process ends, all of its process-private globals are deleted.
-
Process-specific: a process-private global can only be accessed by the process that created it, and it ceases to exist when the process completes. This is similar to local variables.
-
Always public: a process-private global is always a public variable. This is similar to global variables.
-
Namespace-independent: a process-private global is accessible from all namespaces.
-
Unaffected by argumentless KILL, NEW, WRITE, or ZWRITE. A process-private global can be specified as an argument to KILL, WRITE, or ZWRITE. This is similar to global variables.
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.
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.
Apart from the prefix, process-private globals use the same naming conventions as regular globals, as given in Rules and Guidelines for Identifiers. Briefly:
-
The first character (after the second vertical bar) must be either a letter or the percent (%) character.
Process-private variable names starting with % are known as “percent variables” and have different scoping rules. In your code, for these variables, start the name with %Z or %z; other names are reserved for system use. For example: ^||%zmyvar.
-
Unlike local variables, no global name (including process-private globals) can contain Unicode letters — letter characters above ASCII 255. Attempting to include a Unicode letter in a process-private global name results in a <WIDE CHAR> error.
-
All variable names are case-sensitive, and this includes process-private global names.
-
A process-private global name must be unique within its process.
-
Unlike local variables, process-private global names are limited to 31 characters, exclusive of the prefix characters. You may specify a name longer than 31 characters, but only the first 31 characters are used. Therefore, a process-private global name must be unique within its first 31 characters.
-
Like other variables, process-private globals can take subscripts. See Rules About Subscripts.
Listing Process-Private Globals
You can use the ^$||GLOBAL() syntax form of ^$GLOBAL() to return information about process-private globals belonging to the current process.
You can use the ^GETPPGINFO routine to display the names of all 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 specifying 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"
NEW $NAMESPACE
SET $NAMESPACE="%SYS"
DO ^GETPPGINFO("*")
The ^GETPPGINFO routine takes arguments as follows:
do ^GETPPGINFO("pdf","options","outfile")
These arguments are as follows:
-
pdf can be a process Id or the * wildcard.
-
options can be a string containing any combination of the following characters:
-
b (return values in bytes)
-
Mnn (list only processes with process-private globals that use nn or more blocks)
Use M0 to include processes without any process-private globals in the listing.
Use M1 to exclude processes without any process-private globals from the listing, but include processes having only a global directory block. (This is the default.)
Use M2 to exclude processes without any process-private globals from the listing, as well as those having only a global directory block.
-
S (suppress screen display; used with outfile)
-
T (display process totals only).
-
-
outfile 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 globals to an output file named ppgout. The S option suppresses screen display; the M500 option limits output to only processes with process-private globals that use 500 or more blocks:
NEW $NAMESPACE
SET $NAMESPACE="%SYS"
DO ^GETPPGINFO("*","SM500","/home/myspace/ppgout")
Rules About Subscripts
Local variables, process-private variables, and global variables can all take subscripts. In all cases, note the following points:
-
A subscript can be a numeric or a string. It can include any characters, including Unicode characters. Valid numeric subscripts include positive and negative numbers, zero, and fractional numbers.
-
The empty string ("") is not a valid subscript.
-
Subscript values are case-sensitive.
-
Any numeric subscript is converted to canonical form. Thus, for example, the global nodes ^a(7), ^a(007), ^a(7.000), and ^a(7.) are all the same because the subscript is actually the same in all cases.
-
A string subscript is not converted to canonical form. Thus, for example, ^a("7"), ^a("007"), ^a("7.000"), and ^a("7.") are all different global nodes because these subscripts are all different. Also, ^a("7") and ^a(7) both refer to the same global node, because these subscripts are the same.
-
There are limits on the length of a subscript and on the number of subscript levels. See Subscript Limits.
Also see General System Limits.
Lock name subscripts follow the same conventions as variable subscripts.
You can use the $QSUBSCRIPT function to return the components (name and subscripts) of a specified variable, or the $QLENGTH function to return the number of subscript levels.
Variable Typing and Conversion
Variables in ObjectScript are untyped — there are no specified data types. (This is also true of JavaScript, VBScript, and Document Data Base/JSON.) 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, InterSystems IRIS may use different internal representations for strings, integers, numbers, and objects, but this is not visible to the application programmer. InterSystems IRIS 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.",!
InterSystems IRIS converts values as follows:
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 String-to-Number Conversion. 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. |
#dim (Optional)
Unlike other languages, you do not need to declare variables in ObjectScript. You can, however, use the #dim preprocessor directive as an aid to documenting and writing code; IDEs can take advantage of this and provide code-completion assistance.
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.
Global Variables and Journaling
InterSystems IRIS 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 until the transaction that made the changes has been committed. Refer to Transaction Processing for further details.
In contrast, InterSystems IRIS does not treat a SET or KILL of a local variable or a process-private global as a journaled transaction event; rolling back the transaction has no effect on these operations.
Special Variables
ObjectScript includes 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 InterSystems IRIS and are named with a $ character prefix. Users cannot define additional special variables. The special variables are available in 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.
Refer to the ObjectScript Reference for a list and detailed descriptions of the special variables.