Data Types
Data types define the kinds of values that can be manipulated using OScript. The OScript language contains many of the standard programming data types with which you are probably familiar, and also includes additional data types that make working in the Livelink Builder environment easier. OScript supports package-specific data types (listed in the OScript Built-In Function online help) and many fundamental data types. The following list describes each data type and the initial value of a variable declared to be of that type:
When you declare a variable, you can declare it to be of a particular data type. A variable of type Dynamic can take on any data type. Any variable to which a value is assigned without the variable first being declared is considered to be Dynamic -- it can take on a value of any data type (for example Integer, Object, String), and can change from type to type as needed.
Value versus Reference Data Types
OScript language has a rich set of data types that can be placed into two groups -- value data types and reference data types.
A value data type, for example, an Integer or a Date, contains an actual value. It is copied when it is assigned or passed as a parameter. The original value is not affected by any changes to the copy.
Integer original = 55 Integer copyOfOriginal = original original = 0 //At this point, copyOfOriginal still has the value 55
A reference data type, for example, an Assoc or a Record, contains a reference to a value. All variables based on a reference data type point to a shared value, but do not actually contain the value itself. If this value changes, all variables based on the value are changed as well.
Assoc a Assoc b = a// both a and b reference the same Assoc a.arnold = 'toronto' a.amy = 'london'// both a and b associate the value // london with the amy key b.amy = 'beijing'// both a and b now associate the value // beijing with the amy key
The following table categorizes the OScript core data types:
Value data types | Reference data types |
Boolean | Assoc |
Date | Object |
Error | RecArray |
Integer | Record |
List | |
Real | |
String | |
Undefined |
Note that the Dynamic data type assumes the same type as the value it was last assigned.
If an OScript programmer wishes to have a function which modifies a value data type that is passed in, the function must return the modified value as its result, rather than modifying the value directly. For example:
// example that works function Integer Increment( Integer inArg ) return inArg + 1 end //example that does not work function void Increment( Integer inArg ) inArg += 1 end
The second function will simply increment a copy of inArg and then discard it upon returning from the function.
However, a function which modifies a reference data type that is passed in, modifies the value directly without explicitly returning the modified value as its result.
Assoc a a.joe = 'chicago' ModAssoc( a ) function void ModAssoc( Assoc a ) a.joe = 'hong kong' end
After the ModAssoc function executes, a.joe contains the String 'hong kong'.
Assoc data types are associative arrays of arbitrary key-value pairs. Values can be added or retrieved by referencing the appropriate key. Assoc keys can be of any data type but are often specified as Strings (this is not required). If String keys are used, the key is not case sensitive. If a nonexistent key is referenced for a given Assoc, its default value (which defaults to Undefined if not otherwise set using the Assoc.CreateAssoc() function) is returned.
Assoc values can be obtained by:
The following examples illustrate adding and retrieving values with an Assoc.
Assoc namesAndNumbers namesAndNumbers.Lucy = "312/555-4587" namesAndNumbers.Joe = "510/555-9986" namesAndNumbers.Amy = "773/555-1142" namesAndNumbers.Arnold = "510/555-4722"
In the above example, an Assoc of names and phone numbers is created and populated. String keys corresponding to people's names are used to reference String phone numbers.
StringeachKey, notFound ListnamesList = Assoc.Keys( namesAndNumbers ) for eachKey in namesList Echo( eachKey, "'s number is: ", namesAndNumbers.( eachKey ) ) end notFound = namesAndNumbers.Steve
In the above example, all the names and corresponding phone numbers stored in the namesAndNumbers Assoc are displayed by looping through a List containing all of the Assoc keys. However, since there is no Steve key in this Assoc, Undefined is assigned to notFound.
For a complete list of Assoc built-ins, see the OScript Built-In Function online help.
A Boolean represents a two-state value, either TRUE or FALSE. Boolean values can be obtained by:
Boolean expressions are created by using relational or logical operators to form an expression whose result is either TRUE or FALSE. For more information about relational and logical operators, see the Operators section.
For example, if these variables are declared:
String dataLine Integer count Real x, y Boolean library Records, newRecord
The following are all valid Boolean expressions:
dataLine != "" count <= 5000 y < x libraryRecord && newRecord
Booleans are often used as test criteria in conditional structures. For example:
Boolean done while !done textLine = File.Read( myFile ) allLines += ( textLine + Str.EOL() ) done = File.EOF( myFile ) end
In this example, the Boolean expression !done is evaluated and then script execution branches or continues depending on whether the Boolean expression evaluates to TRUE or FALSE.
For a complete list of Boolean built-ins, see the OScript Built-In Function online help.
A Date represents a calendar date and time (for example May 27, 1993, 1:35 am). Dates are stored in an internal, platform-independent format and should not be confused with String representations of dates. Although "11/30/82" looks like a Date, it is actually a String representation of a date and cannot be stored in a Date variable or manipulated as an OScript Date.
Variables declared to be of type Date are initially Undefined. Dates include both the calendar date and the time, but either can be manipulated independently, if needed. Therefore, there is no such thing as a Time data type. A time is considered a special case of a Date -- one for which the day, month, and year information is ignored.
Date values can be obtained by executing a function that returns a Date value. For more information about these built-in functions, see the function syntax in the OScript Built-In Function online help. The most common functions used to generate new Date values are the Date.Now() function, used to generate a Date value representing the current date and time, and the Date.StringToDate() function, used to generate a Date value corresponding to a String representation of a Date. The following example illustrates:
String stringDate = "03/23/89" Date nowDate = Date.Now() Date thenDate = Date.StringToDate( stringDate, "%m/%d/%y" )
In this example, the second parameter in the Date.StringToDate() function is a formatted String that tells the function how to interpret the supplied String. Type conversions can be performed to convert Strings to Dates (to perform Date manipulation) and to convert Dates to Strings (for display purposes) using the Date.StringToDate() and the Date.DateToString() functions.
Arithmetic operations can be performed on Dates to obtain a Date earlier or later than the supplied Date.
For example, you can add or subtract an Integer number of seconds to or from a Date:
Date rightNow, hourFromNow, tomorrow rightNow = Date.Now() hourFromNow = rightNow + ( 60 * 60 ) tomorrow = rightNow + ( 60 * 60 * 24 )
Or you can use the Date.DateInteger() function and the Date.TimeInteger() function to add and subtract days from Dates:
Integer laterInt Date laterDate, today today = Date.Now() laterInt = Date.DateInteger( today ) + 10 laterDate = Date.DateInteger(today, laterint )
In this example, the laterDate value is obtained by converting the Date returned by the Date.Now() function to an Integer, adding ten days to it, and then converting it back to a Date.
For a complete list of Date built-ins, see the OScript Built-In Function online help.
An Error represents either a system-defined or user-defined Error. Errors can be used not only to indicate if an operation failed or was successful (in which case a Boolean would suffice), but also to indicate why a failure occurred. For example, if you attempt to copy a file to the desktop, the process can either succeed or fail. If it fails, it could be because the file to copy cannot be found, because the destination disk is full, because a file with that name already exists, and so on. A specific Error can be generated for each case, allowing the application designer to determine the reason the function failed.
An Error can be thought of as containing two parts -- the Integer error identifier and the String error message. Errors are referred to in scripts by their error identifiers, but the error message can be used to provide the user with information about the type of error that occurred.
There are two types of Errors used in OScript:
The following example illustrates the definition of user-defined Errors:
Error.Define( 1024, "Cannot find specified file." ) Error.Define( 2000, "File already exists." ) Error.Define( 2047, "Out of range." )
Once an Error type is defined, it exists for the remainder of the application execution. It is not disposed of when the script creating the Error completes execution.
Values of type Error are obtained by executing the Error.Get() function. The following example illustrates:
function Boolean checkRange( Integer checkValue ) Boolean returnValue Error negative = Error.Define( 2001, "Negative" ) if ( checkValue < 0 ) // Return the negative value error. returnValue = negative else if ( checkValue > 1000 ) // Return the out of range error. returnValue = Error.Get( 2047 ) else returnValue = TRUE end return( returnValue ) end
Unlike most other OScript data types, any type of variable can assume an Error value. This allows you to create a variable of any type and store a valid value in it if the operation was successful, or store an Error in it if the operation failed.
For a complete list of Error built-ins, see the OScript Built-In Function online help.
A File represents a reference to an operating system file. Files are stored in an internal format and should not be confused with String representations of a file specification (that is, "C:\Data\expenses.xls" is not an OScript file).
When you declare a variable to be of type File, it initially assumes a value of Undefined. A File value can be obtained by opening or selecting a reference to a file using the File.Open function or by converting a String representation of a file name to a File using the File.StringToFile() function.
File readFile = File.Open( "textfile.txt", File.ReadMode )
In the above example a file is opened in preparation for reading.
String fileName = "c:\data\textfile.txt" File theFile = File.StringToFile( fileName )
In the above example, a String file name is converted to an OScript file.
The return value of any of these functions is a File -- the reference to the specified file. A variable containing the File can then be passed to other built-in functions that expect a File parameter.
Some of the built-in functions that operate on files expect the File to be an ASCII text file (for example the File.Open() and File.Write() functions); however, OScript does not prevent you from referencing a non-text file. The File.IsText() function can be used to verify that the referenced File is a text file before proceeding.
For a complete list of File built-ins, see the OScript Built-In Function online help.
An OScript Integer is a 32-bit signed Integer and can take on any value in the range of -2,147,483,648 to 2,147,483,647.
Integer values can be obtained by:
Integer expressions are created by joining two or more Integers (using the arithmetic or bitwise operators) to form an expression whose result is another Integer. The following example illustrates:
Integer theLength = Length( "abcdefghijklmno" ) Integer shorter = ( theLength - 10 )
Arithmetic expressions can be created containing a mixture of Reals and Integers. When this is done, Integer math operations are performed until a Real is encountered. From that point on, Real math operations are performed.
For a complete list of Integer built-ins, see the OScript Built-In Function online help.
A List represents a one-dimensional array of values. Each element in the List can be of any data type (including List).
When you declare a variable to be of type List, it is initially empty. List values can be obtained by using a List literal or by executing a function that returns a List value (for example the Str.Elements() function).
ListnamesList = { "Amy", Naomi", "Arnold, "Miki", "Blanca" } Listvalues = { namesList, ( 21 + 6 ), Date.Now() }
In the above example, a List literal is created by defining a set of values, surrounded by braces and separated by commas. Note that the elements in the List need not be literals; they can be other Lists, expressions, or functions.
The expansion operator ( @ ) can be used to reference all elements contained in a List, rather than the List itself. This is useful to insert the contents of a List into another List. For example:
templist = { "Bruce", "Toronto", 81 } tempList = { @tempList, 34, "dog", TRUE }
In this example, tempList is assigned a new value consisting of the current contents of tempList with the addition of three elements. Without the expansion operator, the first element of the new List would be the original List. With the expansion operator, the original List's elements are inserted as separate elements in the new List.
The elements contained within a List can be referenced using the index operator
( [ ] ), where the first element in the List is element 1. For example, the fourth element of the List
variable myList can be obtained
using the following syntax:
DynamictheValue = myList[ 4 ]
The range operator ( : ) can be used to define a range of elements to form a subset. The following example illustrates:
Listwords = Str.Elements( "Now is the time", " " ) ListfirstThree = words[ 1:3 ]
In the above example, firstThree will contain the value:
{ "Now", "is", "the" }
You can use an open-ended range, for example, [ : 6 ] specifies a range from the beginning through the 6th element, and [ 3: ] specifies a range from the third through the last element.
You can also refer to List elements using negative numbers, where the last element of the List is -1. For example, myList[ -2:-1 ] returns a List containing the last two elements of myList.
For a complete list of List built-ins, see the OScript Built-In Function online help.
An expression of type Object is a reference to an OSpace object. OScript can access the features and methods of other objects via an object reference.
An object is created and manipulated with the built-in functions in the OS (OSpace) package. In fact, it is these functions that underlie the Livelink Builder's Object menu commands. The features of an object (both data features and methods) are referenced with the dot operator as objectName.featureName.
For example, if you create an object reference feature named logInfoObj in the UserPkg object that refers to the LogInfo object, you can reference the fName method of LogInfo from a script within UserPkg using the following syntax:
.logInfoObj.fName
The this keyword references the current object without using the object's name:
this.fName
If you create a global variable named $logInfo to store the logInfoObj object reference, you can reference the fName method of LogInfo from any script using the following syntax:
$LogInfo.fName
Creating a global variable to refer to an object allows any object to reference that object from any OSpace.
A Real is a double-precision floating point number, and can therefore take on any positive or negative value in the range of 1.0E-308 to 1.0E307, with fifteen digit precision.
Real values can be obtained by:
Real expressions are created by joining two or more numbers, at least one of which is a Real (the others can be Integers), using the arithmetic operators to form an expression whose result is another Real. The following example illustrates:
Integerdollars = 2000 RealtaxPercentage = .33 RealgrossPay = dollars * ( 1 - taxPercentage )
Arithmetic expressions can be created containing a mixture of Reals and Integers. When this is done, Integer math operations are performed until a Real is encountered. From this point on, Real math operations are performed.
In OScript, there is a strong relationship between RecArrays and Records, so they are presented together.
A RecArray is a reference to a two-dimensional array. It contains multiple rows of data, called Records, each made up of named fields. A RecArray is similar in structure to a table in a standard SQL database.
You can create a RecArray by executing the RecArray.Create() function:
RecArraymyRecArray = RecArray.Create( { "name", "role" } )
This function creates a new RecArray with the specified fields and composed of no Records. The field names specified must be String values. Data can be entered into the RecArray using the RecArray.AddRecord() function or by using the dot operator. For more information, see the Dot Operator section within the Operators section.
An individual Record within a RecArray can be referenced using the index operator ( [ ] ), where the first Record in the RecArray is Record 1.
For example, the first Record of the RecArray variable myRecArray can be obtained using the following syntax:
RecordfirstRecord = myRecArray[ 1 ]
The expression used within the brackets must evaluate to an Integer. For example, to access the last Record in a RecArray, you could use the following statement:
RecordlastRecord = myRecArray[ Length( myRecArray ) ]
Records can be declared and used independently of RecArrays -- they need not only be used within the context of a RecArray. However, an Assoc is used more often than a "solo" Record.
An individual field within a Record can be referenced using the dot operator ( . ), where the expression following the dot identifies the desired field. This field can be specified by field name, Integer field position (where the first field is field 1), or by a String variable, enclosed in parentheses, that evaluates to a valid field name.
For example:
RecArraymyRecArray RecordtheRecord myRecArray = RecArray.Create( {"name", "modDate", "saveDate" } ) // the contents of the name field of the first Record myRecArray[ 1 ].name // the contents of the second field of the eleventh Record myRecArray[ 11 ][ 2 ] // the contents of the third field of the fifth Record theRecord = myRecArray[ 5 ] theRecord[ 3 ]//same as theRecord.saveDate // the contents of the modDate field of the fifth Record theRecord = myRecArray[ 5 ] theRecord.modDate // the contents of the modDate field of the fifth // Record (using variable) theRecord = myRecArray[ 5 ] String s = "modDate" theRecord.(s)//same as theRecord.modDate
A String expression can be used to specify a field reference when placed inside parentheses. This can be useful in looping constructs. For example:
function List columnData( RecArray dataTable, String colName ) Integer i List listOfValues for i = 1 to Length( dataTable ) listOfValues[ i ] = dataTable[ i ].( colName ) end return( listOfValues ) end
For a complete list of RecArray built-ins, see the OScript Built-In Function online help.
A String is any sequence of zero or more characters. String values can be obtained by:
String literals consist of a sequence of zero or more characters delimited by either single or double quotation marks. For example:
String myName = "Arnold Wilson" String myBDay = 'August 20th, 1934'
Single or double quotation marks can be embedded in the String by alternating the delimiters used or by doubling the desired quotation character. For example:
String phrase1 = 'The proper term is "regardless."' String phrase2 = "She can''t understand." String phrase3 = "His name is John "Rusty"" Smith"
Note that there are two single quotation characters between the n and the t in the String phrase2.
Strings can be concatenated using the + operator. For example:
String myString = 'This is a test.' Echo( myString + ' Really.' ) //displays 'This is a test. Really.'
Substrings can be deleted from a String using the - operator. When using the - operator to delete substrings, only the first occurrence of the substring (read from left to right) is removed from the String. If the substring is not found, an Error does not occur. For example:
String myString = "This is a test." Echo( myString - "is" )//displays "Th is a test." Echo( myString - "is" - "is" )//displays "Th a test."
The characters in a String can be referenced using the index operator ( [ ] ), where the first character in the String is character 1. For example, the sixth and seventh characters of the String variable myString can be referenced using the following syntax:
String myString = "this is a test." myString[ 1 ] = Str.Upper( myString[ 1 ] ) Echo( myString )//displays "This is a test." myString[ 6 : 7 ] = "is not" Echo( myString )//displays "This is not a test."
You can use an open-ended range, for example, [ : 6 ] specifies a range from the beginning through the 6th character of the String, and [ 3: ] specifies a range from the third through the last character of the String.
You can also refer to String characters using negative numbers, where the last character of the String is -1. For example, myString[ -2:-1 ] returns a String containing the last two characters of myString.
For more information about the operators used with Strings, see the Arithmetic section and the Indexing section within the Operators section. For a complete list of String built-ins, see the OScript Built-In Function online help.
Undefined is both a data type and a unique value that any data type may take on, indicating the lack of another data type value. It can be used as a value against which variables can be compared to determine whether a value has been assigned. The IsDefined() and IsUndefined() functions can be used to determine if a result is Undefined. For example:
FiletheFile = File.Open( "textfile.txt", File.ReadMode )
if ( IsUndefined ( theFile ) )
echo( "A valid file was not selected" )
else
...block of code...
end
Many built-in functions return Undefined when they fail.
Type Conversion and Coercion
When expressions are created using operands of differing data types, they must first be converted to a common type. The only automatic conversions that OScript makes are those that make intuitive sense, for example, converting an Integer to a Real to perform an arithmetic operation, resulting in a Real.
The OScript language contains many type conversion built-in functions. These functions allow you to explicitly convert a value from one data type to another. There are too many type conversion functions to be listed here; they can be found throughout the OScript Built-In Function online help. To locate a function for performing a particular kind of type conversion follow these guidelines:
OScript also allows certain kinds of data type coercion. Coercion differs from conversion in that coercion does not actually change a value from one type to another, but allows a data type to be treated as if it were another type. In OScript, various data types can be coerced into Boolean values, according to the following table:
Data type | Coerced to | Evaluates to | When |
Date | Boolean | TRUE | at all times |
Error | Boolean | FALSE | at all times |
Integer | Boolean | TRUE | nonzero |
List | Boolean | TRUE | not empty |
Real | Boolean | TRUE | nonzero |
String | Boolean | TRUE | not empty |
Undefined | Boolean | FALSE | at all times |
Boolean | Integer/Real | 0 | when FALSE |
Boolean | Integer/Real | 1 | when TRUE |
Real (a.b) | Integer | a | stored in an Integer variable |
Note that for the Real to Integer coercion, values are truncated rather than rounded. Therefore, the value 3.6 becomes 3, rather than 4.