# Data Types and Values

ObjectScript is a typeless language — you do not have to declare the types of variables. Any variable can have a string, numeric, or object value. That being said, there is important information to know when using different kinds of data in ObjectScript, such as:

## Strings

A string is a set of characters: letters, digits, punctuation, and so on delimited by a matched set of quotation marks ("):

SET string = "This is a string" WRITE string

Topics about strings include:

### Null String / $CHAR(0)

SET mystr="": sets a null or empty string. The string is defined, is of zero length, and contains no data:

SET mystr="" WRITE "defined:",$DATA(mystr),! WRITE "length: ",$LENGTH(mystr),! ZZDUMP mystr

Copy code to clipboardSET mystr=$CHAR(0): sets a string to the null character. The string is defined, is of length 1, and contains a single character with the hexadecimal value of 00:

SET mystr=$CHAR(0) WRITE "defined:",$DATA(mystr),! WRITE "length: ",$LENGTH(mystr),! ZZDUMP mystr

Copy code to clipboard

Note that these two values are not the same. However, a bitstring treats these values as identical.

Note that InterSystems SQL has its own interpretation of these values. Refer to NULL and the Empty String in the “Language Elements” chapter of Using Caché SQL.

### Escaping Quotation Marks

You can include a " (double quote) character as a literal within a string by preceding it with another double quote character:

SET string = "This string has ""quotes"" in it." WRITE string

There are no other escape character sequences within ObjectScript string literals.

Note that literal quotation marks are specified using other escape sequences in other InterSystems software. Refer to the $ZCONVERT function for a table of these escape sequences.

### Concatenating Strings

You can concatenate two strings into a single string using the _ concatenate operator:

SET a = "Inter" SET b = "Systems" SET string = a_b WRITE string

By using the concatenate operator you can include non-printing characters in a string. The following string includes the linefeed ($CHAR(10)) character:

SET lf = $CHAR(10) SET string = "This"_lf_"is"_lf_"a string" WRITE string

How non-printing characters display is determined by the display device. For example, Terminal differs from browser display of the linefeed character, and other positioning characters. In addition, different browsers display the positioning characters $CHAR(11) and $CHAR(12) differently.

Caché encoded strings — bit strings, List structure strings, and JSON strings — have limitations on their use of the concatenate operator. For further details, see Concatenate Encoded Strings.

Some additional considerations apply when concatenating numbers. For further details, see “Concatenating Numbers”.

### String Comparisons

You can use the equals (=) and does not equal ('=) operators to compare two strings. String equality comparisons are case-sensitive. Exercise caution when using these operators to compare a string to a number, because this comparison is a string comparison, not a numeric comparison. Therefore only a string containing a number in canonical form is equal to its corresponding number. ("-0" is not a canonical number.) This is shown in the following example:

WRITE "Fred" = "Fred",! // TRUE WRITE "Fred" = "FRED",! // FALSE WRITE "-7" = -007.0,! // TRUE WRITE "-007.0" = -7,! // FALSE WRITE "0" = -0,! // TRUE WRITE "-0" = 0,! // FALSE WRITE "-0" = -0,! // FALSE

The <, >, <=, or >= operators cannot be used to perform a string comparison. These operators treat strings as numbers and always perform a numeric comparison. Any non-numeric string is assigned a numeric value of 0 when compared using these operators.

#### Lettercase and String Comparisons

String equality comparisons are case-sensitive. You can use the $ZCONVERT function to convert the letters in the strings to be compared to all uppercase letters or all lowercase letters. Non-letter characters are unchanged.

A few letters only have a lowercase letter form. For example, the German eszett ($CHAR(223)) is only defined as a lowercase letter. Converting it to an uppercase letter results in the same lowercase letter. For this reason, when converting alphanumeric strings to a single letter case it is always preferable to convert to lowercase.

### Long Strings

Caché supports two maximum string length options:

The traditional maximum string length of 32,767 characters.

Long Strings maximum string length of 3,641,144 characters.

Long strings are enabled by default. If long strings are enabled, the maximum length of a string is 3,641,144 characters. If long strings are disabled, the maximum length of a string is 32,767 characters.

Attempting to exceed the current maximum string length results in a <MAXSTRING> error.

You can return the current system-wide maximum string length by invoking the MaxLocalLength() method, as follows:

WRITE $SYSTEM.SYS.MaxLocalLength()

You can use any of the following operations to enable or disable long strings system-wide:

In the Management Portal, select System, Configuration, Memory and Startup. On the System Memory and Startup Settings page, select the Enable Long Strings check box.

In the Caché parameter file (CPF file), specify the value of the EnableLongStrings parameter, as described in the EnableLongStrings section of the Caché Parameter File Reference.

In the Config.Miscellaneous class properties, specify an EnableLongStrings boolean value. This modifies the corresponding CPF file parameter. For example:

ZNSPACE "%SYS" SET getstat=##class(Config.Miscellaneous).Get(.Properties) IF getstat '= 1 {WRITE "Get config property error",! QUIT} SET Properties("EnableLongStrings")=0 SET modstat=##class(Config.Miscellaneous).Modify(.Properties) IF modstat '= 1 {WRITE "Modify config property error",! QUIT}

Copy code to clipboard

When a process actually uses a long string, the memory for the string comes from the operating system’s malloc() buffer, not from the partition memory space for the process. Thus the memory allocated for actual long string values is not subject to the limit set by the maximum memory per process (Maximum per Process Memory (KB)) parameter and does not affect the $STORAGE value for the process.

### Bit Strings

A bit string represents a logical set of numbered bits with boolean values. Bits in a string are numbered starting with bit number 1. Any numbered bit that has not been explicitly set to boolean value 1 evaluates as 0. Therefore, referencing any numbered bit beyond those explicitly set returns a bit value of 0.

Bit values can only be set using the bit string functions $BIT and $BITLOGIC.

Bit values can only be accessed using the bit string functions $BIT, $BITLOGIC, and $BITCOUNT.

A bit string has a logical length, which is the highest bit position explicitly set to either 0 or 1. This logical length is only accessible using the $BITCOUNT function, and usually should not be used in application logic. To the bit string functions, an undefined global or local variable is equivalent to a bitstring with any specified numbered bit returning a bit value 0, and a $BITCOUNT value of 0.

A bit string is stored as a normal Caché string with an internal format. This internal string representation is not accessible with the bit string functions. Because of this internal format, the string length of a bit string is not meaningful in determining anything about the number of bits in the string.

Because of the bit string internal format, you cannot use the concatenate operator with bit strings. Attempting to do so results in an <INVALID BIT STRING> error.

Two bit strings in the same state (with the same boolean values) may have different internal string representations, and therefore string representations should not be inspected or compared in application logic. To the bit string functions, the null strings and undefined global/local variables are equivalent to a bitstring with all bits 0, and a length of 0.

Unlike an ordinary string, a bit string treats the empty string and the character $CHAR(0) to be equivalent to each other and to represent a 0 bit. This is because $BIT treats any non-numeric string as 0. Therefore:

SET $BIT(bstr1,1)="" SET $BIT(bstr2,1)=$CHAR(0) SET $BIT(bstr3,1)=0 IF $BIT(bstr1,1)=$BIT(bstr2,1) {WRITE "bitstrings are the same"} ELSE {WRITE "bitstrings different"} WRITE $BITCOUNT(bstr1),$BITCOUNT(bstr2),$BITCOUNT(bstr3)

A bit set in a global variable during a transaction will be reverted to its previous value following transaction rollback. However, rollback does not return the global variable bit string to its previous string length or previous internal string representation. Local variables are not reverted by a rollback operation.

A logical bitmap structure can be represented by an array of bit strings, where each element of the array represents a "chunk" with a fixed number of bits. Since undefined is equivalent to a chunk with all 0 bits, the array can be sparse, where array elements representing a chunk of all 0 bits need not exist at all. For this reason, and due to the rollback behavior above, application logic should avoid depending on the length of a bit string or the count of 0-valued bits accessible using $BITCOUNT(str) or $BITCOUNT(str,0).

## Numbers

Topics related to numbers include:

### Fundamentals of Numbers

Numeric literals do not require any enclosing punctuation. You can specify a number using any valid numeric characters. Caché evaluates a number as syntactically valid, then converts it to canonical form.

The syntactic requirements for a numeric literal are as follows:

It can contain the decimal numbers 0 through 9, and must contain at least one of these number characters. It can contain leading or trailing zeros. However, when InterSystems IRIS converts a number to canonical form it automatically removes leading integer zeros. Therefore, numbers for which leading integer zeros are significant must be input as strings. For example, United State postal Zip Codes can have a leading integer zero, such as 02142, and therefore must be handled as strings, not numbers.

It can contain any number of leading plus and minus signs in any sequence. However, a plus sign or minus sign cannot appear after any other character, except the “E” scientific notation character. In a numeric expression a sign after a non-sign character is evaluated as an addition or subtraction operation. In a numeric string a sign after a non-sign character is evaluated as a non-numeric character, terminating the number portion of the string.

Caché uses the PlusSign and MinusSign property values for the current locale to determine these sign characters (“+” and “-” by default); these sign characters are locale-dependent. To determine the PlusSign and MinusSign characters for your locale, invoke the GetFormatItem() method:

WRITE ##class(%SYS.NLS.Format).GetFormatItem("PlusSign"),! WRITE ##class(%SYS.NLS.Format).GetFormatItem("MinusSign")

Copy code to clipboardIt can contain at most one decimal separator character. In a numeric expression a second decimal separator results in a <SYNTAX> error. In a numeric string a second decimal separator is evaluated as the first non-numeric character, terminating the number portion of the string. The decimal separator character may be the first character or the last character of the numeric expression. The choice of decimal separator character is locale-dependent: American format uses a period (.) as the decimal separator, which is the default. European format uses a comma (,) as the decimal separator. To determine the DecimalSeparator character for your locale, invoke the GetFormatItem() method:

WRITE ##class(%SYS.NLS.Format).GetFormatItem("DecimalSeparator")

Copy code to clipboardIt can contain at most one letter “E” (or “e”) to specify a base-10 exponent for scientific notation. This scientific notation character (“E” or “e”) must be preceded by a integer or fractional number, and followed by an integer.

Numeric literal values do not support the following:

They cannot contain numeric group separators. These are locale-dependent: American format uses commas, European format uses periods. You can use the $INUMBER function to remove numeric group separators, and the $FNUMBER function to add numeric group separators.

They cannot contain currency symbols, hexadecimal letters, or other nonnumeric characters. They cannot contain blank spaces, except before or after arithmetic operators.

They cannot contain trailing plus or minus signs. However, the $FNUMBER function can display a number as a string with a trailing sign, and the $NUMBER function can take a string in this format and convert it to a number with a leading sign.

They cannot specify enclosing parentheses to represent a number as a negative number (a debit). However, the $FNUMBER function can display a negative number as a string with a enclosing parentheses, and the $NUMBER function can take a string in this format and convert it to a number with a leading negative sign.

A number or numeric expression can containing pairs of enclosing parentheses. These parentheses are not part of the number, but govern the precedence of operations. By default, Caché performs all operations in strict left-to-right order.

### Canonical Form of Numbers

ObjectScript performs all numeric operations on numbers in their canonical form. For example, the length of the number +007.00 is 1; the length of the string "+007.00" is 7.

When Caché converts a number to canonical form, it performs the following steps:

Scientific notation exponents are resolved. For example 3E4 converts to 30000 and 3E-4 converts to .0003.

Leading signs are resolved. First, multiple signs are resolved to a single sign (for example, two minus signs resolve to a plus sign). Then, if the leading sign is a plus sign, it is removed. You can use the $FNUMBER function to append a plus sign to a positive Caché canonical number.

Note:ObjectScript resolves any combination of leading plus and minus signs. In SQL, two consecutive minus signs are parsed as a single-line comment indicator. Therefore, specifying a number in SQL with two consecutive leading minus signs results in an SQLCODE -12 error.

All leading and trailing zeros are removed. This includes removing leading integer zeroes, including the leading integer zero from fractions smaller than 1. For example 0.66 becomes .66.

To append an integer zero to a canonical fraction use the $FNUMBER or $JUSTIFY function. .66 becomes 0.66.

To remove integer zeroes from a non-canonical fraction use the Unary Plus operator to force conversion of a number string to a canonical number. In the following example, the fractional seconds portion of a timestamp, +$PIECE("65798,00000.66",",",2). 00000.66 becomes .66.

As part of this conversion, zero fractions are simplified to 0. Regardless of how expressed (0.0, .0, .000) all zero values are converted to 0.

A trailing decimal separator is removed.

-0 is converted to 0.

Arithmetic operations and numeric concatenation are performed. Caché performs these operations in strict left-to-right order. Numbers are in their canonical form when these operations are performed. For further details, refer to Concatenating Numbers below.

Caché canonical form numbers differ from other canonical number formats used in InterSystems software:

ODBC: Integer zero fractions converted to ODBC have a zero integer. Therefore, .66 and 000.66 both become 0.66. You can use the $FNUMBER or $JUSTIFY function to append an integer zero to a Caché canonical number.

JSON: Only a single leading minus sign is permitted; a leading plus sign or multiple signs are not permitted.

Exponents are permitted but not resolved. 3E4 is returned as 3E4.

Leading zeros are not permitted. Trailing zeros are not removed.

Integer zero fractions must have a zero integer. Therefore, .66 and 000.66 are not valid JSON numbers, but 0.66 and 0.660000 are valid JSON numbers.

A trailing decimal separator is not permitted.

Zero values are not converted: 0.0, -0, and -0.000 are returned unchanged as valid JSON numbers.

### Strings as Numbers

The following are the general rules for handling strings as numbers. For further details, refer to String-to-Number Conversion in the “Operators and Expressions” chapter of this book.

For all numeric operations, a string containing a number in canonical form is functionally identical to the corresponding number. For example, "3" = 3, "-2.5" = -2.5. (Note that -0 is not a canonical number.)

For arithmetic operations, a string containing only numeric characters in non-canonical form is functionally identical to the corresponding number. For example, "003" + 3 = 6, "++-2.5000" + -2.5 = -5.

For greater-than/less-than operations, a string containing only numeric characters in non-canonical form is functionally identical to the corresponding number. For example, the following statements are true: "003" > 2, "++-2.5000" >= -2.5.

For equality operations (=, '=), a string containing only numeric characters in non-canonical form is treated as a string, not a number. For example, the following statements are true: "003" = "003", "003" '= 3, "+003" '= "003".

Some further guidelines concerning parsing strings as numbers:

A mixed numeric string is a string that begins with numeric characters, followed by one or more non-numeric characters. For example “7 dwarves”. Caché numeric and boolean operations (other than equality operations) commonly parse a mixed numeric string as a number until they encounter a non-numeric character. At that point the rest of the string is ignored. The following example shows arithmetic operations on mixed numeric strings:

WRITE "7dwarves" + 2,! // returns 9 WRITE "+24/7" + 2,! // returns 26 WRITE "7,000" + 2,! // returns 9 WRITE "7.0.99" + 2,! // returns 9 WRITE "7.5.99" + 2,! // returns 9.5

Copy code to clipboardA non-numeric string is any string in which a non-numeric character is encountered before encountering a numeric character. Note that a blank space is considered a non-numeric character. Caché numeric and boolean operations (other than equality operations) commonly parse this string as having a numeric value of 0 (zero). The following example shows arithmetic operations on non-numeric strings:

WRITE "dwarves 7" + 2,! // returns 2 WRITE "+ 24/7" + 2,! // returns 2 WRITE "$7000" + 2,! // returns 2

Copy code to clipboardYou can prefix a string with a plus sign to force its evaluation as a number for equality operations. A numeric string is parsed as a number in canonical form; a non-numeric string is parsed as 0. (A minus sign prefix also forces evaluation of a string as a number for equality operations; the minus sign, of course, inverts the sign for a non-zero value.) The following example shows the plus sign forcing numeric evaluation for equality operations:

WRITE +"7" = 7,! // returns 1 (TRUE) WRITE +"+007" = 7,! // returns 1 (TRUE) WRITE +"7 dwarves" = 7,! // returns 1 (TRUE) WRITE +"dwarves" = 0,! // returns 1 (TRUE) WRITE +"" = 0,! // returns 1 (TRUE)

Copy code to clipboard

Numeric string handling exceptions for individual commands and functions are common, as noted in the Caché ObjectScript Reference.

### Concatenating Numbers

A number can be concatenated to another number using the concatenate operator (_). Caché first converts each number to its canonical form, then performs a string concatenation on the results. Thus, the following all result in 1234: 12_34, 12_+34, 12_--34, 12.0_34, 12_0034.0, 12E0_34. The concatenation 12._34 results in 1234, but the concatenation 12_.34 results in 12.34. The concatenation 12_-34 results in the string “12-34”.

Caché performs numeric concatenation and arithmetic operations on numbers after converting those numbers to canonical form. It performs these operations in strict left-to-right order, unless you specify parentheses to prioritize an operation. The following example explains one consequence of this:

WRITE 7_-6+5 // returns 12

In this example, the concatenation returns the string “7-6”. This, of course, is not a canonical number. Caché converts this string to a canonical number by truncating at the first non-numeric character (the embedded minus sign). It then performs the next operation using this canonical number 7 + 5 = 12.

### Fractional Numbers

Caché supports two different numeric types that can be used to represent fractional numbers:

Decimal floating-point: By default, Caché represents fractional numbers using its own decimal floating-point standard ($DECIMAL numbers). This is the preferred format for most uses. It provides the highest level of precision — 18 decimal digits. It is consistent across all system platforms that Caché supports. Decimal floating-point is preferred for data base values. In particular, a fractional number such as 0.1 can be exactly represented using decimal floating-point notation, while the fractional number 0.1 (as well as most decimal fractional numbers) can only be approximated by binary floating-point.

Binary floating-point: The IEEE double-precision binary floating point standard is an industry-standard way of representing fractional numbers. IEEE floating point numbers are encoded using binary notation. Binary floating-point representation is usually preferred when doing high-speed calculations because most computers include high-speed hardware for binary floating-point arithmetic. Double-precision binary floating point has a precision of 53 binary bits, which corresponds to 15.95 decimal digits of precision. Binary representation does not correspond exactly to a decimal fraction because a fraction such as 0.1 cannot be represented as a finite sequence of binary fractions. Because most decimal fractions cannot be exactly represented in this binary notation, an IEEE floating point number may differ slightly from the corresponding standard Caché floating point number. When an IEEE floating point number is displayed as a fractional number, the binary bits are often converted to a fractional number with far more than 18 decimal digits. This does not mean that IEEE floating point numbers are more precise than standard Caché fractional numbers. IEEE floating point numbers are able to represent larger and smaller numbers than standard Caché numbers, and support the special values INF (infinity) and NAN (not a number). For further details, refer to the $DOUBLE function.

You can use the $DOUBLE function to convert a Caché standard floating-point number to an IEEE floating point number. You can use the $DECIMAL function to convert an IEEE floating point number to a Caché standard floating-point number.

By default, Caché converts fractional numbers to canonical form, eliminating all leading zeros. Therefore, 0.66 becomes .66. $FNUMBER (most formats) and $JUSTIFY (3-parameter format) always return a fractional number with at least one integer digit; using either of these functions, .66 becomes 0.66.

$FNUMBER and $JUSTIFY can be used to round or pad a numeric to a specified number of fractional digits. Caché rounds up 5 or more, rounds down 4 or less. Padding adds zeroes as fractional digits as needed. The decimal separator character is removed when rounding a fractional number to an integer. The decimal separator character is added when zero-padding an integer to a fractional number.

### Scientific Notation

To specify scientific (exponential) notation in ObjectScript, use the following format:

[-]mantissaE[-]exponent

where

- | Optional — One or more Unary Minus or Unary Plus operators. These PlusSign and MinusSign characters are configurable. Conversion to canonical form resolves these operators after resolving the scientific notation. |

mantissa | An integer or fractional number. May contain leading and trailing zeros and a trailing decimal separator character. |

E | An operator delimiting the exponent. The uppercase “E” is the standard exponent operator; the lowercase “e” is a configurable exponent operator, using the ScientificNotation() method of the %SYSTEM.Process class. |

- | Optional — A single Unary Minus or Unary Plus operator. Can be used to specify a negative exponent. These PlusSign and MinusSign characters are configurable. |

exponent | An integer specifying the exponent (the power of 10). Can contain leading zeros. Cannot contain a decimal separator character. |

For example, to represent 10, use 1E1. To represent 2800, use 2.8E3. To represent .05, use 5E-2.

No spaces are permitted between the mantissa, the E, and the exponent. Parentheses, concatenation, and other operators are not permitted within this syntax.

Because resolving scientific notation is the first step in converting a number to canonical form, some conversion operations are not available. The mantissa and exponent must be numeric literals, they cannot be variables or arithmetic expressions. The exponent must be an integer with (at most) one plus or minus sign.

See the ScientificNotation() method of the %SYSTEM.Process class.

### Extremely Large Numbers

The largest integers that can be represented exactly are the 19-digit integers -9223372036854775808 and 9223372036854775807. This is because these are the largest numbers that can be represented with 64 signed bits. Integers larger than this are automatically rounded to fit within this 64-bit limit. This is shown in the following example:

SET x=9223372036854775807 WRITE x,! SET y=x+1 WRITE y

Similarly, exponents larger that 128 may also result in rounding to permit representation within 64 signed bits. This is shown in the following example:

WRITE 9223372036854775807e-128,! WRITE 9223372036854775807e-129

Because of this rounding, arithmetic operations that result in numbers larger than these 19-digit integers have their low-order digits replaced by zeros. This can result in situations such as the following:

SET longnum=9223372036854775790 WRITE longnum,! SET add17=longnum+17 SET add21=longnum+21 SET add24=longnum+24 WRITE add17,!,add24,!,add21,! IF add24=add21 {WRITE "adding 21 same as adding 24"}

The largest Caché decimal floating point number supported is 9.223372036854775807E145. The largest supported $DOUBLE value (assuming IEEE overflow to INFINITY is disabled) is 1.7976931348623157081E308. The $DOUBLE type supports a larger range of values than the Caché decimal type, while the Caché decimal type supports more precision. The Caché decimal type has a precision of approximately 18.96 decimal digits (usually 19 digits but sometimes only 18 decimal digits of precision) while the $DOUBLE type usually has a precision around 15.95 decimal digits (or 53 binary digits). By default, Caché represents a numeric literal as a decimal floating-point number. However, if the numeric literal is larger than what can be represented in Caché decimal (larger than 9.223372036854775807E145) Caché automatically converts that numeric value to $DOUBLE representation.

A numeric value larger than 1.7976931348623157081E308 (308 or 309 digits) results in a <MAXNUMBER> error.

Because of the automatic conversion from decimal floating-point to binary floating-point, rounding behavior changes at 9.223372036854775807E145 (146 or 147 digits, depending on the integer). This is shown in the following examples:

TRY { SET a=1 FOR i=1:1:310 {SET a=a_1 WRITE i+1," digits = ",+a,! } } CATCH exp { WRITE "In the CATCH block",! IF 1=exp.%IsA("%Exception.SystemException") { WRITE "System exception",! WRITE "Name: ",$ZCVT(exp.Name,"O","HTML"),! WRITE "Location: ",exp.Location,! WRITE "Code: " } ELSE { WRITE "Some other type of exception",! RETURN } WRITE exp.Code,! WRITE "Data: ",exp.Data,! RETURN }

TRY { SET a=9 FOR i=1:1:310 {SET a=a_9 WRITE i+1," digits = ",+a,! } } CATCH exp { WRITE "In the CATCH block",! IF 1=exp.%IsA("%Exception.SystemException") { WRITE "System exception",! WRITE "Name: ",$ZCVT(exp.Name,"O","HTML"),! WRITE "Location: ",exp.Location,! WRITE "Code: " } ELSE { WRITE "Some other type of exception",! RETURN } WRITE exp.Code,! WRITE "Data: ",exp.Data,! RETURN }

You can represent a number longer than 309 digits as a numeric string. Because this value is stored as a string rather than a number, neither rounding nor the <MAXNUMBER> error apply:

SET a="1" FOR i=1:1:360 {SET a=a_"1" WRITE i+1," characters = ",a,! }

Exponents that would result in a number with more than the maximum permitted number of digits generate a <MAXNUMBER> error. The largest permitted exponent depends on the size of the number that is receiving the exponent. For a single-digit mantissa, the maximum exponent is 307 or 308.

For further details on large number considerations when using Caché decimal numbers or IEEE double numbers, see the appendix “Numeric Computing in InterSystems Applications” in the Caché Programming Orientation Guide.

## Objects

An object value refers to an instance of an in-memory object. You can assign an object reference (OREF) to any local variable:

ZNSPACE "SAMPLES" SET myperson = ##class(Sample.Person).%New() WRITE myperson

To refer to the methods and properties of an object instance, use dot syntax:

SET myperson.Name = "El Vez"

To determine if a variable contains an object, use the $ISOBJECT function:

SET str = "A string" SET myperson = ##class(Sample.Person).%New() IF $ISOBJECT(myperson) { WRITE "myperson is an object.",! } ELSE { WRITE "myperson is not an object." } IF $ISOBJECT(str) { WRITE "str is an object." } ELSE { WRITE "str is not an object." }

You cannot assign an object value to a global. Doing so results 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, as shown in the following example:

ZNSPACE "SAMPLES" SET x = ##class(Sample.Person).%New() WRITE x,! SET y = ##class(Sample.Person).%New() WRITE y,! SET z = ##class(Sample.Person).%New() WRITE z,!

When the number of references to an object reaches 0, the system automatically destroys the object (invoke its %OnClose() callback method and remove it from memory).

## Persistent Multidimensional Arrays (Globals)

A global is a sparse, multidimensional database array. A global is not different from any other type of array, with the exception that the global variable name starts with a caret (^). Data can be stored in a global with any number of subscripts; subscripts in Caché are typeless.

The following is an example of using a global. Once you set the global ^x, you can examine its value:

SET ^x = 10 WRITE "The value of ^x is: ", ^x,! SET ^x(2,3,5) = 17 WRITE "The value of ^x(2,3,5) is: ", ^x(2,3,5)

For more information on globals, see the “Multidimensional Arrays” chapter in this document and the Using Caché Globals document.

## Undefined Values

ObjectScript variables do not need to be explicitly declared or defined. As soon as you assign a value to a variable, the variable is defined. Until this first assignment, all references to this variable are undefined. You can use the $DATA function to determine if a variable is defined or undefined.

$DATA takes one or two arguments. With one argument, it simply tests if a variable has a value:

WRITE "Does ""MyVar"" exist?",! IF $DATA(MyVar) { WRITE "It sure does!" } ELSE { WRITE "It sure doesn't!" } SET MyVar = 10 WRITE !,!,"How about now?",! IF $DATA(MyVar) { WRITE "It sure does!" } ELSE { WRITE "It sure doesn't!" }

$DATA returns a boolean that is True (1) if the variable has a value (that is, contains data) and that is False (0) if the variable has no value (that is, contains no data). With two arguments, it performs the test and sets the second argument’s variable equal to the tested variable’s value:

IF $DATA(Var1,Var2) { WRITE "Var1 has a value of ",Var2,".",! } ELSE { WRITE "Var1 is undefined.",! } SET Var1 = 3 IF $DATA(Var1,Var2) { WRITE "Var1 has a value of ",Var2,".",! } ELSE { WRITE "Var1 is undefined.",! }

## Boolean Values

In certain cases, such as when used with logical commands or operators, a value may be interpreted as a boolean (true or false) value. In such cases, an expression is interpreted as 1 (true) if evaluates to a nonzero numeric value or 0 (false) if it evaluates to a zero numeric value. A numeric string evaluates to its numeric value; a non-numeric string evaluates to 0 (false).

For example, the following values are interpreted as true:

IF 1 { WRITE "evaluates as true",! } ELSE { WRITE "evaluates as false",! } IF 8.5 { WRITE "evaluates as true",! } ELSE { WRITE "evaluates as false",! } IF "1 banana" { WRITE "evaluates as true",! } ELSE { WRITE "evaluates as false",! } IF 1+1 { WRITE "evaluates as true",! } ELSE { WRITE "evaluates as false",! } IF -7 { WRITE "evaluates as true",! } ELSE { WRITE "evaluates as false",! } IF +"007"=7 { WRITE "evaluates as true",! } ELSE { WRITE "evaluates as false",! }

The following values are interpreted as false:

IF 0 { WRITE "evaluates as true",! } ELSE { WRITE "evaluates as false",! } IF 3-3 { WRITE "evaluates as true",! } ELSE { WRITE "evaluates as false",! } IF "one banana" { WRITE "evaluates as true",! } ELSE { WRITE "evaluates as false",! } IF "" { WRITE "evaluates as true",! } ELSE { WRITE "evaluates as false",! } IF -0 { WRITE "evaluates as true",! } ELSE { WRITE "evaluates as false",! } IF "007"=7 { WRITE "evaluates as true",! } ELSE { WRITE "evaluates as false",! }

For further details on the evaluation of a string as a number, refer to String-to-Number Conversion in the “Operators and Expressions” chapter of this book.

## Dates

ObjectScript has no built-in date type; instead it includes a number of functions for operating on and formatting date values represented as strings. These date formats include:

Format | Description |
---|---|

$HOROLOG | This is the format returned by the $HOROLOG ($H) special variable. It is a string containing two comma-separated integers: the first is the number of days since December 31, 1840; the second is the number of seconds since midnight of the current day. $HOROLOG does not support fractional seconds. The $NOW function provides $HOROLOG-format dates with fractional seconds. Caché provides a number of functions for formatting and validating dates in $HOROLOG format. |

ODBC Date | This is the format used by ODBC and many other external representations. It is a string of the form: “YYYY-MM-DD HH:MM:SS”. ODBC date values will collate; that is, if you sort data by ODBC date format, it will automatically be sorted in chronological order. |

Locale Date |
This is the format used by the current locale. Locales differ in how they format dates as follows:
“American” dates are formatted mm/dd/yyyy (dateformat 1). “European” dates are formatted dd/mm/yyyy (dateformat 4). All locales use dateformat 1 except the following — csyw, deuw, engw, espw, eurw, fraw, itaw, mitw, ptbw, rusw, skyw, svnw, turw, ukrw — which use dateformat 4.
American dates use a period (.) as a decimalseparator for fractional seconds. European dates use a comma (,) as a decimalseparator for fractional seconds, except the following — engw, eurw, skyw — which use a period.
All locales use a slash (/) as the dateseparator character, except the following, which use a period (.) as the dateseparator character — Czech (csyw), Russian (rusw), Slovak (skyw), Slovenian (svnw), and Ukrainian (ukrw). |

System Time | This is the format returned by the $ZHOROLOG ($ZH) special variable. It is a floating point number containing the number of seconds (and parts thereof) that the system has been running. Stopping and restarting Caché resets this number. Typically this format is used for timing and testing operations. |

The following example shows how you can use the different date formats:

Date Formats

SET now = $HOROLOG WRITE "Current time and date ($H): ",now,! SET odbc = $ZDATETIME(now,3) WRITE "Current time and date (ODBC): ",odbc,! SET ldate = $ZDATETIME(now,-1) WRITE "Current time and date in current locale format: ",ldate,! SET time = $ZHOROLOG WRITE "Current system time ($ZH): ",time,!