Xbasic GuideArrays, Object Pointer Variables, and Collections

In addition to simple data types – such as character, date, or time – Xbasic includes several built-in data structures for storing multiple related values together in a single variable. Arrays, collections (U), and object pointer variables (P) are data types that store multiple values in a single variable. These data structures include methods for doing things such as setting values, getting values, or retrieving information about the data structure.

Arrays

An array is a sequential series of data values of the same data type. Individual entries in an array are accessed using an index. Arrays are useful for collecting and processing sets of information, such as a set of scores or a list of names.

Declaring Arrays

An array can be declared as any data type (A, B, C, D, K, L, N, P, T, U, and Y.) Arrays are explicitly defined using the DIM statement with the bracket [] operator to declare the array's size. For example:

DIM names[5] as C

The example above declares a character array called names with a size of 5.

If the size of your array is unknown when you need to create it, you can declare it as a dynamic array. Dynamic arrays are declared by specifying zero (0) for the array size:

DIM locations[0] as C

Values can be assigned to an entry in an array using the bracket [] operator and a numeric value that indicates what entry in the array to update. In the example below, five names are assigned to the names array:

names[1] = "Amanda Higgins"
names[2] = "Nancy Clark"
names[3] = "Diane Morton"
names[4] = "John Rhodes"
names[5] = "Cecelia Dawkins"

Xbasic arrays are 1-indexed, meaning the first entry in the array is at index 1.

? names[1]
= "Amanda Higgins"

? names[5]
= "Cecelia Dawkins"

Declaring Arrays with Default Values

Arrays can be assigned a default value when they are declared using the assignment = operator. For example:

DIM str[4] AS C  = "Default"
? str 
= [1] = "Default"
[2] = "Default"
[3] = "Default"
[4] = "Default"

The default value can be a literal (e.g., the string "Default" is a literal) or an expression. For example:

DIM nums[4] AS N = rand()
? nums
= [1] = 0.44000244140625
[2] = 0.837158203125
[3] = 0.128662109375
[4] = 0.797760009765625

In this example, the nums array is declared with a default value of rand(). The rand() function returns a random value between 0 and 1. The result is an array that contains 4 random numbers.

Adding New Entries to an Array

New entries can be added to an array using one of the following array methods: push(), append(), or insert(). These methods increase an array's size to make room for the new entry.

The push() method adds a value to the end of an array. For example:

locations.push("Ann Arbor,MI")

When the example executes, a new entry is created at the end of the locations array and set to the value "Ann Arbor, MI":

? locations
= [1] = "Ann Arbor,MI"

The push() method can be used with any array to add new entries. For example, push() can be used to add a new entry to the names array, which was created with a size of 5:

names.push("Matt Stevens")

After pushing a new value onto the end of the names array, the array now has six entries. EG:

? names[6]
= "Matt Stevens"

The array's append() method also adds new entries to the end of an array. append() creates a new blank entry at the end of the array and returns the index:

DIM newIndex AS N = names.append()

The index is used to set the value of the new entry:

names[newIndex] = "Lisa Hobbs"

If you need to add entries to the middle of an array, use the insert() method. The array insert() method adds one or more array entries at the specified index. For example, the code below inserts two new array entries in the names array at index:

names.insert(2,2)

After inserting new the array entries, you can assign a value to the new entries:

names[2] = "Peter Williams"
names[3] = "Anise Vanderbilt"

When the names array is output in the Interactive Window, it displays the list shown below:

? names
= [1] = "Amanda Higgins"
[2] = "Peter Williams"
[3] = "Anise Vanderbilt"
[4] = "Nancy Clark"
[5] = "Diane Morton"
[6] = "John Rhodes"
[7] = "Cecelia Dawkins"
[8] = "Matt Stevens"

Any Arrays

The data type contained in the array can be any valid variable data type, including the Any (A) data type. Assigning a value to an Any array element is similar to assign a value to a character or numeric array. When a value is assigned to an Any array, however, the data is added as an object pointer with one property: value. value contains the value of the entry in the Any array. You must use the value property to read the value from the array. For example:

DIM arr[3] AS A
arr[1] = "char"
arr[2] = 5
arr[3] = now()

? arr[1]
= VALUE = "char"

? arr[1].value
= "char"

Multidimensional Arrays

Xbasic arrays can contain also contain multiple dimensions. For example, the following statement declares an array with 3 dimensions:

DIM a[1,1,3] as C

Assigning a value to a multidimensional array is done as follows:

a[1,1,1] = "First"
a[1,1,2] = "Second"
a[1,1,3] = "Third"

? a
= [1,1,1] = "First"
[1,1,2] = "Second"
[1,1,3] = "Third"

Looping Through Array Entries

The entries in an array are indexed sequentially starting at 1. You can loop or iterate over all the values of an array using a FOR loop to access each entry in the array. For example:

DIM values[10] AS N = rand()*10
DIM i AS N
DIM total AS N = 0
FOR i = 1 TO values.size()
    total = values[i] + total
NEXT i
showvar(total)

This example computes the total sum of all entries in the values array. The variable i is used to access the current element in the array in the FOR loop (values[i]) and add it to the total. The size() method returns the size of the array. Using the size() method lets you create a loop that is independent of the size of the array, which is useful in cases where you don't know the size of the array.

The size() method takes an optional parameter that can be used to request the size for a specific dimension in a multidimensional array. For example:

DIM a[4,2] AS N
? a.size(1)
= 4

? a.size(2)
= 2

size(1) returns the size for the first dimension of the array, which is the value 4. size(2) returns the size for the second dimension of the array, which is the value 2.

The size() method can be used to create nested loops to iterate over every value in a multidimensional array. For example:

DIM i AS N
DIM j AS N
FOR i = 1 TO a.size(1)
    FOR j = 1 TO a.size(2)
        a[i,j] = j
    NEXT j
NEXT i

? a
= [1,1] = 1
[1,2] = 2
[2,1] = 1
[2,2] = 2
[3,1] = 1
[3,2] = 2
[4,1] = 1
[4,2] = 2

In this example, the multidimensional array a is populated by iterating over each entry in the array. The nested FOR loops are used to compute the index for the first and second dimension. a[i,j] = j assigns the value of j to the array entry located at [i,j].

Array Methods

Xbasic arrays have multiple methods for working with arrays, including initializing array values, adding and removing entries, sorting, searching, exporting arrays to other formats, and getting information about the array (such as the array size.) We've shown how to use several array methods, including the push(), append(), insert(), and size() methods. In this section, we'll show how to perform some common tasks using arrays.

To learn more about the methods available for working with Xbasic arrays, see Array Methods.

  • Initializing an Array using a Character List

    An array can be populated with a character list using the array initialize() method. For example:

    DIM people AS C =<<%str%
    Amanda Higgins
    Nancy Clark
    Diane Morton
    John Rhodes
    Cecelia Dawkins
    %str%
    
    DIM names2[0] AS C
    names2.initialize(people)
    
    ? names2 
    = [1] = "Amanda Higgins"
    [2] = "Nancy Clark"
    [3] = "Diane Morton"
    [4] = "John Rhodes"
    [5] = "Cecelia Dawkins"
  • Merging two Arrays

    You can combine multiple arrays of the same type into a single array using the append_arrays() method. append_arrays() copies the entries from one or more arrays and adds them to the end of an array. For example, the Xbasic below merges the trees and shrubs arrays into a new array, plants:

    DIM trees[0] AS C
    trees.push("Oak")
    trees.push("Pine")
    
    DIM shrubs[0] AS C
    shrubs.push("Lilac")
    shrubs.push("Forsythia")
    
    DIM plants[0] AS C
    plants.append_arrays(trees,shrubs)
    ? plants
    = [1] = "Oak"
    [2] = "Pine"
    [3] = "Lilac"
    [4] = "Forsythia"

    Arrays can only be merged if they are the same type and have one dimension. Attempting to merge two arrays of different types or merging multidimensional arrays will result in an error.

  • Deleting an Array Entry

    Deleting array entries is done using the delete() method. The delete() method takes two arguments: the index of the first element to delete and the number of elements to delete.

    DIM fruit[5] AS C
    fruit[1] = "Orange"
    fruit[2] = "Banana"
    fruit[3] = "Pear"
    fruit[4] = "Apple"
    fruit[5] = "Pineapple"
    ? fruit
    = [1] = "Orange"
    [2] = "Banana"
    [3] = "Pear"
    [4] = "Apple"
    [5] = "Pineapple"
    
    fruit.delete(2,2)  ' Delete "Banana" and "Pear"
    ? fruit
    = [1] = "Orange"
    [2] = "Apple"
    [3] = "Pineapple"
    [4] = ""
    [5] = ""

    If the array was declared with a fixed size, the empty array entries are moved to the end of the array, as shown in the example above. If the array was declared as a dynamic array, the entries are deleted and the array is resized:

    DIM melons[0] AS C
    melons.push("Honeydew")
    melons.push("Cantaloupe")
    melons.push("Watermelon")
    melons.push("Casaba")
    ? melons
    = [1] = "Honeydew"
    [2] = "Cantaloupe"
    [3] = "Watermelon"
    [4] = "Casaba"
    
    melons.delete(3) ' Delete "Watermelon"
    ? melons
    = [1] = "Honeydew"
    [2] = "Cantaloupe"
    [3] = "Casaba"
  • Sorting an Array

    Arrays can be sorted using the sort() method. Several optional parameters can be passed to the sort() method that define how to sort the array ("A" - ascending, "D" - descending).

    dim numbers[10] as N = floor(rand()*100)+2
    ? numbers
    = [1] = 2
    [2] = 14
    [3] = 67
    [4] = 20
    [5] = 83
    [6] = 57
    [7] = 56
    [8] = 39
    [9] = 40
    [10] = 88
    
    numbers.sort("A")
    ? numbers
    = [1] = 2
    [2] = 14
    [3] = 20
    [4] = 39
    [5] = 40
    [6] = 56
    [7] = 57
    [8] = 67
    [9] = 83
    [10] = 88

    If the array is a property array, you can specify which property should be used to sort the array. For example, the Xbasic below sorts the parents array using the value in the mom property. The data is sorted alphabetically from A-Z (ascending):

    DIM parents[2] AS P
    parents[1].mom = "Irene"
    parents[1].dad = "Abe"
    parents[2].mom = "Arlene"
    parents[2].dad = "Kyle"
    parents.sort("A","mom")

    See Array sort Method to learn more about how to use the sort() method.

  • Searching an Array

    The find() and findi() methods can be used to search an array. Both methods return the index of the location of the first element that matches the search expression. If no entries in the array match, the method returns 0. For example:

    DIM squares[0] AS N
    DIM num AS N
    
    FOR num  = 1 TO 10
        squares.push(num*num)
    NEXT num
    
    ? squares.find(36)
    = 6
    
    ? squares[6]
    = 36

    The find() and findi() functions behave the same for all array types except character arrays. If the value to find is a character string, find() does a case-sensitive search while findi() does a case-insensitive search.

    DIM furniture[0] AS C
    furniture.push("Chair")
    furniture.push("Table")
    furniture.push("Lamp")
    furniture.push("Sofa")
    
    ? furniture.find("sofa")
    = 0
    
    ? furniture.findi("sofa")
    = 4
    
    ? furniture[4]
    = "Sofa"

Object Pointer Variables

An object pointer, declared using the P type, is a special variable type in Xbasic that can contain multiple values defined as properties of the variable. Dot notation is used to define and access properties for object pointers. For example:

DIM person AS P
person.age = 47
person.firstName = "Liza"
person.lastName = "Stevens"
person.deceased = .F.

Object Pointers are Dot Variables

Object pointers are also referred to as "dot variables" or "pointer variables." These terms are used interchangeably throughout the Alpha Anywhere documentation. For consistency, we call them object pointers in this guide.

You can use the DIM statement to add a property to an object pointer without assigning a value.

DIM person.address AS C

Properties can be any valid Xbasic variable type, including arrays, function pointers, and object pointers.

When passed to a function, object pointers are always passed by reference (BYREF). This means if the parameter is modified by the function, it changes the object pointer in the calling code. In the Interactive Window session shown below, the lastname property is added to the person variable by calling the lastname() function.

FUNCTION lastname AS V (person AS P)
    person.lastname = "Smith"
END FUNCTION

DIM p1 AS P
p1.firstname = "Janet"

? p1
= firstname = "Janet"

lastname(p1)

? p1
= firstname = "Janet"
lastname = "Smith"

Adding Methods to Object Pointer

Xbasic object pointers have methods that can be used to set and get values from the object. You can also add methods by adding function pointers as properties to the object pointer:

DIM obj AS P
obj.pet_name = "Savvy"
obj.breed = "Tuxedo"
obj.species = "Cat"

FUNCTION sayMeow AS V ()
    showvar("Meow!","Say 'Meow'")
END FUNCTION

DIM obj.speak AS F = sayMeow
obj.speak()

Object Pointer Arrays (Property Arrays)

A variable can be declared as an array of object pointers by declaring the array as type P. Referred to as "property arrays," each entry in a property array is an object pointer. For example:

DIM usPlaces[2] AS P
usPlaces[1].city = "Boston"
usPlaces[1].state = "MA"
usPlaces[2].city = "Atlanta"
usPlaces[2].state = "GA"

The code above defines a property array called usPlaces with a size of two. Each object pointer in the array is assigned a city and state property. The table below is a graphical representation of the property array defined above:

array element

city

state

usPlaces[1]

Boston

MA

usPlaces[2]

Atlanta

GA

  • Dynamic Property Arrays

    New entries can be added to property arrays using the append() method. Properties can then be added to the new entry using the index returned by the append() method. For example:

    dim pArr[0] as P
    i = pArr.append()
    pArr[i].name = "Fred"
    pArr[i].city = "Boston"
    pArr[i].age = 23
    
    i = pArr.append()
    pArr[i].name = "Tom"
    pArr[i].city = "NY"
    pArr[i].age = 35
    	
    ? pArr.dump_properties("Name|city|age")
    = Fred|Boston|23
    Tom|NY|35

    Property arrays also support special bracket syntax for adding new entries to the array, which you may encounter in Xbasic found in the Alpha Anywhere documentation or user forum. The syntax uses the [] and [..] array operators. The [] operator creates a new element at the end of the array, and the [..] operator adds properties to the last element in the array.

    dim pArr2[1] as P
    pArr2[1].name = "Fred"
    pArr2[1].city = "Boston"
    pArr2[1].age = 23
    
    pArr2[].name = "Tom"
    pArr2[..].city = "NY"
    pArr2[..].age = 35
    
    ? pArr2.dump_properties("Name|city|age")
    = Fred|Boston|23
    Tom|NY|35

    In the code shown above, a[].name = "Tom" adds array element number 2. a[..]. city = "NY" adds "NY" to the newly created array element (i.e. number 2).

    While this syntax is supported, it is not a recommended best practice to use [] and [..] to dynamically append elements to a property array. If you forget to use [..] to add properties and instead use [], you can end up in the following scenario:

    dim pArr3[0] as p
    pArr3[].name = "Fred"
    pArr3[].city = "Boston"
    pArr3[].age = 23
    pArr3[].name = "Tom"
    pArr3[].city = "NY"
    pArr3[].age = 35
    
    ? pArr3.dump_properties("Name|city|age")
    = Fred||
    |Boston|
    ||23
    Tom||
    |NY|
    ||35

    Instead of creating two array entries with a name, city, and age property, the script creates an array that contains six entries with a name, city, or age property. To avoid this issue, use the append() method.

  • Using Property Arrays with JSON Data

    Object pointer arrays can be used with JSON data in Xbasic. JSON is used on the client in UX controls, such as the List and ViewBox, as well as by web services, including the Alpha TransForm API. When working with JSON data in Xbasic, it is often easier to convert the JSON into an object pointer to work with the data.

    DIM json AS C =<<%json%
    [
        {"fname":"Alicia","lname":"Davis","city":"Springfield","state":"VA"},
        {"fname":"Reuben","lname":"Hayes","city":"Anchorage","state":"AK"},
        {"fname":"Joel","lname":"Kay","city":"Boise","state":"ID"}
    ]
    %json%
    
    DIM people AS P
    people = json_parse(json)

    When you're done manipulating the data, it can be serialized back into JSON before sending it to the client.

    json = json_generate(people)

Built-in Xbasic Objects

Xbasic Objects are global variables available to your scripts. Built-in Xbasic objects are similar to object pointer variables in that they have properties. They also often contain methods -- functions you can call. Two objects frequently used in web applications are the context and TRACE objects.

The context object contains the Response, Request, Security, and Session objects. These four objects store state information for web applications and provide methods to read and write cookies, handle web page redirects, work with the security framework, and store data in the user's session.

context.request

This object represents the parsed HTTP request that was received by the Application Server and has several properties and methods.

context.response

This object represents the HTTP response created by the Application Server and sent back to the client. It has several properties and methods. The server creates this object for each Response and can be accessed directly by your applications.

context.session

This object contains data about an individual user's session, including session variables and temporary session files.

context.security

This object contains properties and methods available for working with the users and roles if a web application uses security.

The TRACE object is useful for logging messages in the server logs. It can be used in both the development environment and published applications. Messages written to the TRACE logs can be accessed either in the Trace Window (Developer IDE) or the Trace Folder on the Application Server. TRACE logs on Alpha Cloud can also be accessed through the Alpha Cloud interface in the Developer IDE.

Another object you may also use is the FILE object. FILE is used for working with files stored on the server running Alpha Anywhere. FILE is not supported on Alpha Cloud.

You can find information about available objects in the Xbasic Objects documentation.

Collections

A collection is an Xbasic datatype, similar to an array, but whose elements are referenced with a key rather than an index. A collection is declared using the data type U:

DIM collection AS U

Elements are added to a collection using the set() method. The set() method takes two parameters: a key and a value. The key is a character, numeric, or date value that uniquely identifies an element in a collection. The value is the data stored in the collection for the specified key and can be any value or expression that evaluates to a single value. For example:

DIM people AS U
people.set("FJ","Fred Jones")
people.set("BB","Bryan Boyd")
people.set("KL","Kim Lee")

In the code example above, a collection is created named people, and three entries are added to the collection using the set() method.

To get the value in a collection, you can use the get() method. The get() method takes a key and returns the value. For example, the Xbasic below retrieves and prints the value for the key "BB" for the people collection:

? people.get("BB")
= "Bryan Boyd"

By contrast, in an array, elements are referred to by index number. In the array shown below, the second element corresponds to the value "Bryan Boyd."

DIM persons[0] AS C
persons.push("Fred Jones")
persons.push("Bryan Boyd")
persons.push("Kim Lee")

? persons[2]
= "Bryan Boyd"

See "Collection Methods" to learn more about collections.