# 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.
```pascal
// 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.
```pascal
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.
```pascal
// 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);
// OUTPUT
// 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.
```pascal
// 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(', '));
// OUTPUT
// 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.
```pascal
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] ]
));
// OUTPUT
// 5, 25, 60
```
:::warning
**Indexing Gotcha:** Arrays are **0-indexed**. See **[Indexing Strategy](/lang/basics/types#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.
```pascal
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);
// OUTPUT
// 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.
```pascal
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');
// OUTPUT
// 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. |
```pascal
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:
```pascal
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);
// OUTPUT
// Dot Product: 11
```
:::info
#### 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.
```pascal
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');
// OUTPUT
// 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. |
```pascal
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(', '));
// OUTPUT
// 1, 4, 9, 16, 25
// 2, 4
```
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 Integersvar 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]ofInteger;
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 arrayvar arr :arrayofInteger;// Initialized with 3 elements, but can still growvar data :arrayofInteger:=[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 expansionvar nums :=[1..3,10,5..1];// Result: [1, 2, 3, 10, 5, 4, 3, 2, 1]// Concatenationvar 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 :arrayofInteger:=[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)forvar i :=0to list.High do
PrintLn(list[i].ToString);// Value-based iteration (for..in)forvar 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 methodif list.Contains(20)then
PrintLn('Found 20');// Using the operator (idiomatic)if30in 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 :arrayofFloat:=[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 :arrayofFloat:=[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:
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 :arrayofInteger;var b :arrayofInteger;if a =nilthen
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 aif a =nilthen
PrintLn('a is nil again');if b <>nilthen
PrintLn('b still has data: '+ b.Length.ToString);// Comparing different empty arraysvar c :arrayofInteger:=[];var d :arrayofInteger:=[];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.