Arrays

DWScript supports two main types of arrays: Static (fixed size) and Dynamic (resizable). The distinction is often determined by how the variable is declared and how type inference is applied.

Static Arrays

Static arrays have a fixed size defined at compile-time. They are efficient and safe when the number of elements is known in advance.

Type Inference

When you use a simple array literal assignment with var, DWScript infers a Static Array. Its size is fixed to the number of elements in the literal.

// Inferred as a Static Array of 3 Integers
var list := [10, 20, 30]; 

// list.Add(40); // Error: Static arrays cannot be resized

Explicit Declaration

You can also explicitly define the range of a static array.

var matrix : array [0..2, 0..2] of Integer;
matrix[1, 1] := 5;

Dynamic Arrays

Dynamic arrays can grow and shrink at runtime. They are the most flexible and commonly used array type in DWScript.

Declaration & Initialization

To create a dynamic array, you must explicitly declare its type using the array of Type syntax.

// Explicitly typed dynamic array
var arr : array of Integer;

// Initialized with 3 elements, but can still grow
var data : array of Integer := [10, 20, 30];

data.Add(40); // Works!
data[0] := 5;

PrintLn('Length: ' + data.Length.ToString);
Result
Length: 4

Resizing Methods

Dynamic arrays support several methods for changing their size:

Method Description
Add(value) Appends an element to the end.
Delete(index) Removes an element.
SetLength(new) Resizes the array directly.
Clear Removes all elements.

Literals & Features

Array literals are powerful and support features like range expansion and concatenation.

// Array literal with range expansion
var nums := [1..3, 10, 5..1]; 
// Result: [1, 2, 3, 10, 5, 4, 3, 2, 1]

// Concatenation
var a := [1, 2] + [3, 4];
a += 5; // Note: This converts 'a' to a Dynamic array if it was static

PrintLn(a.Map(IntToStr).Join(', '));
Result
1, 2, 3, 4, 5

Element Access & Manipulation

Arrays in DWScript are 0-indexed. You can access elements using square brackets. Dynamic arrays also support compound assignment operators directly on their elements.

var data : array of Integer := [10, 20, 30];

// Standard access
data[0] := 5;

// Compound assignment
data[1] += 5; // 25
data[2] *= 2; // 60

PrintLn(Format(
  '%d, %d, %d',
  [ data[0], data[1], data[2] ]
));
Result
5, 25, 60

Indexing Gotcha: Arrays are 0-indexed. See Indexing Strategy for the comparison with Strings.

Iteration & Bounds

You can iterate through arrays using index-based loops or for..in. Index-based loops are generally faster and more explicit when you need the index or specific direction. for..in is convenient when you only need the values and want to avoid manual indexing.

var list := [10, 20, 30];

// Index-based iteration (fastest)
for var i := 0 to list.High do
  PrintLn(list[i].ToString);

// Value-based iteration (for..in)
for var val in list do
  PrintLn(val.ToString);
Result
10
20
30
10
20
30

Search & Membership

You can check if a value exists in an array using the .Contains() method or the more idiomatic in operator.

var list := [10, 20, 30];

// Using the method
if list.Contains(20) then
  PrintLn('Found 20');

// Using the operator (idiomatic)
if 30 in list then
  PrintLn('Found 30');
Result
Found 20
Found 30

Array Methods

Dynamic arrays come with a rich set of built-in methods for manipulation.

Method Description
Add(value) / Push Appends an element to the end. Push is typically used when treating the array as a stack.
Pop Removes and returns the last element.
Peek Returns the last element without removing it.
Insert(index, value) Inserts an element at a specific position.
Delete(index [, count]) Removes one or more elements by index.
Remove(value) Removes the first occurrence of a specific value.
SetLength(newLength) Resizes the array.
Clear Removes all elements.
Sort Sorts the array in-place. Supports an optional lambda for custom comparison.
Reverse Reverses the array in-place.
IndexOf(value [, from]) Returns the index of the first occurrence (at or after from), or -1 if not found.
Contains(value) Returns True if the value exists in the array.

Numerical Processing (Float Arrays)

For array of Float, DWScript provides high-performance vectorized operations. These methods are mutating (they modify the array in-place) and return the array instance to support fluent method chaining.

Method Parameters Description
Offset v Adds v to every element.
Offset other [, targetOff, sourceOff, count] Element-wise addition of other array.
Multiply v Multiplies every element by v.
Multiply other [, targetOff, sourceOff, count] Element-wise multiplication by other array.
MultiplyAdd scale, offset For each element: x := x * scale + offset.
Min v Sets each element to Min(x, v) (caps values at v).
Min other [, targetOff, sourceOff, count] Element-wise x := Min(x, other[i]).
Max v Sets each element to Max(x, v) (floors values at v).
Max other [, targetOff, sourceOff, count] Element-wise x := Max(x, other[i]).
Reciprocal Replaces each element with 1 / x.
DotProduct other Returns the dot product (scalar) with another float array.
var a : array of Float := [1.0, 2.0, 4.0];

// Fluent chaining (mutating)
a.Offset(1).Multiply(2).Max(5.0); 
// Result: [5.0, 6.0, 10.0]

var b : array of Float := [1.0, 2.0, 3.0];
var dot := b.DotProduct([4.0, 5.0, 6.0]); // 32.0 (returns scalar)

High-Performance Array Operations

Many of the numerical processing methods support optional offset and count parameters. This allows performing operations on specific segments of the arrays without creating temporary copies, which is critical for high-performance computing.

The global ArrayDotProduct function also supports these parameters:

var a1 : array of Float := [0, 0, 1, 2, 0];
var a2 : array of Float := [0, 3, 4, 0, 0];

// ArrayDotProduct(arr1, arr2, offset1, offset2, count)
// Performs dot product on segments: [1, 2] . [3, 4] = (1*3 + 2*4) = 11
var dot := ArrayDotProduct(a1, a2, 2, 1, 2);

PrintLn('Dot Product: ' + dot.ToString);
Result
Dot Product: 11

Semantic Aliases

While Add and Push perform the same operation (appending to the end), using Push and Pop conveys a specific architectural intent: that the array is being used as a Stack (LIFO - Last In, First Out).

Comparison & Nil

Dynamic arrays can be compared with nil using the = and <> operators. A dynamic array is considered equal to nil if it is empty (length 0) or has not been initialized.

You can also compare two dynamic arrays with each other. This performs a reference comparison, meaning it checks if both variables point to the same array instance in memory.

Important details:

  • Two different empty arrays are not equal to each other, even if both are equal to nil.
  • Assigning nil to a dynamic array reinitializes it to an empty state but does not affect other variables still referencing the original data.
var a : array of Integer;
var b : array of Integer;

if a = nil then
  PrintLn('a is nil/empty');

a := [1, 2, 3];
b := a;

if a = b then
  PrintLn('a and b point to the same array');

a := nil; // Reinitialize a
if a = nil then
  PrintLn('a is nil again');
if b <> nil then
  PrintLn('b still has data: ' + b.Length.ToString);

// Comparing different empty arrays
var c : array of Integer := [];
var d : array of Integer := [];
if (c = nil) and (d = nil) then
  PrintLn('Both are "nil"');
if c <> d then
  PrintLn('But they are different instances');
Result
a is nil/empty
a and b point to the same array
a is nil again
b still has data: 3
Both are "nil"
But they are different instances

Functional & Transformation Methods

DWScript dynamic arrays support functional programming patterns. These methods return a new array and do not modify the original.

Method Description
Map(lambda) Transforms each element using the provided function.
Filter(lambda) Returns an array containing only elements that satisfy the condition.
Join(separator) Concats all elements into a single string.
var nums : array of Integer := [1, 2, 3, 4, 5];

// Square numbers
var squares := nums.Map(lambda (x: Integer) => x * x); 
PrintLn(squares.Map(lambda (x: Integer) => x.ToString).Join(', '));

// Keep evens
var evens := nums.Filter(lambda (x: Integer) => (x mod 2) = 0);
PrintLn(evens.Map(lambda (x: Integer) => x.ToString).Join(', '));
Result
1, 4, 9, 16, 25
2, 4
On this page