Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Data types

TypeSyntaxWhereDescription
charchar(length)@Fields, @VariablesFixed-length string. length required (1-32,766 in @Fields; 1-16,773,104 in @Variables).
varcharvarchar(length)@Variables onlyVariable-length string. length required (1-16,773,100). Length(...) returns the actual content length at runtime, unlike char.
numbernumber(precision, scale)@Fields, @VariablesNumeric. precision required (1-30 in @Fields; 1-63 in @Variables); scale optional, default 0.
datedate@Fields, @VariablesDate, no parameters. In @Fields it can’t carry Default(...).
timetime@Fields, @VariablesTime (hour/minute/second), no parameters. In @Fields it can’t carry Default(...).
timestamptimestamp@Fields, @VariablesCombined date and time (with microseconds), no parameters. In @Fields it can’t carry Default(...).
fieldfield(FieldName)@Variables onlyInherits the type of a FieldName field from some referenced table’s @Structure.
listlist(type)@Variables onlyDynamic list of type (scalar, struct(Template), or field(...); another nested list or matrix is not allowed, see E00283). No size in the declaration — the maximum internal capacity is fixed (9999 elements) and not configurable. Read/write an element with &Variable[index]; add/remove/query with methods (see List: methods).
matrixmatrix(rows, cols, type)@Variables onlyFixed-size 2D grid of rows x cols of type. Read/write an element with &Variable[row, col].
structstruct(TemplateName)@Variables onlyInstance of a struct TemplateName [ ... ] template defined inline in the global scope (see Struct: templates and member access). Access a member with &Variable.Member.

Examples

@Variables {
    global {
        Username     char(10)
        Destination  varchar(200)
        Balance      number(9,2)
        RegDate      date
        RegTime      time
        RegTimestamp timestamp
        Status       field(ADSTS50)
        List1        list(number(5))
        Board        matrix(8, 8, char(1))
    }
}

char/varchar interoperability

char and varchar interoperate in assignments — the rule is purely about length (the source must fit into the destination), regardless of which one is fixed or variable:

&VarcharDestination = &CharSource  // valid if length(CharSource) <= length(VarcharDestination)
&CharDestination     = &VarcharSource

List/Matrix: indexing

&List1[1] = 100
&Board[3, 5] = "X"

The index is 1-based. List/Matrix are only valid in @Variables, never in @Fields.

List: methods

list carries no size in its declaration (list(type), no capacity parameter): the maximum internal capacity is fixed at 9999 elements, defined by the compiler and not configurable from the language. Instead of a fixed size up front, content is managed through methods, using member syntax (&Variable.Method(...)):

MethodUseDescription
Add(value)statementAppends value to the end of the list. value must be type-compatible with the list’s element type (if the element is struct(Template), value must be a &Variable of that exact same template).
Clear()statementEmpties the list (the element count goes back to 0).
Remove(index)statementRemoves the element at position index (1-based, number type) and shifts the following ones back one position.
Count()expressionReturns the current number of elements (number type). Can only be used inside an expression, never as a standalone statement.
&List1.Add(10)
&List1.Add(20)
&List1.Add(30)

For &i = 1 To &List1.Count()
    // ... &List1[&i] ...
EndFor

&List1.Remove(2)
&List1.Clear()

There’s no For Each over an in-memory list — traversal is done with a classic For counter (For &i = 1 To &List.Count()) plus indexing (&Variable[&i]); For Each In remains exclusive to database tables (see @Source: control statements).

If Add(value) is called while the list is already at its maximum capacity (9999 elements), the program issues a visible dsply with the message Lista {name} alcanzó su capacidad máxima (9999) and does not add the element — it doesn’t abort the whole program.

list(struct(Template)) is valid (a list of instances of the same struct). Nesting list/matrix inside each other is not, in any combination: list(list(...)), list(matrix(...)), matrix(list(...)), and matrix(matrix(...)) produce the compile error E00283 (“‘&{variable}’ es un {list/matrix} cuyo elemento no puede ser {list/matrix} (sin equivalente RPG generable): use un tipo escalar, struct(…) o field(…).”), caught in semantic analysis — it isn’t possible to declare an array whose element is itself another array.

Struct: templates and member access

A named template with members, defined inline inside @Variables’s global scope:

@Variables {
    global {
        struct Person [
            Id      number(10, 0)
            Name    varchar(50)
            Email   varchar(100)
            Age     number(3, 0)
        ]
        globalPerson    struct(Person)
        Name            varchar(50)
    }
    PrintPerson {
        person   struct(Person)
    }
}
&globalPerson.Name = "Your Name"
&Name = &globalPerson.Name
Do PrintPerson(&globalPerson)
  • Template members support char/varchar/number/date/time/timestamp/field(FieldName) — you can’t nest another struct, nor use list/matrix as a member.

  • A member is read/assigned with &Variable.Member (both read and write).

  • It can be passed as a parameter to, and returned from, an in-file Procedure/Function — see Procedure / Function.

  • An array of struct is declared with list(struct(TemplateName)) — see List: methods.

  • Indexing &List[i] on a list(struct(Template)) is valid, but only in two exact forms: as a read, the whole value of an assignment to another &Variable that is struct(...) of the same template (&otherVariable = &List[i]); as a write, &List[i] = &otherVariable (another &Variable struct(...) of the same template, never an expression or a literal). If the side of the assignment that should be the struct variable isn’t syntactically a &Variable, E00241 is reported; if the template doesn’t match exactly the list’s, E00242 is reported. Index checks (count, number type, 1..9999 range) apply the same as for any other list:

    &otherRecord = &List[1]
    &List[1] = &otherRecord
    For &i = 1 To &List.Count()
        &current = &List[&i]
    EndFor
    
  • Not supported yet: a struct nested inside another struct, or struct as a parameter of an external program (@Parameters/Call) — only as a parameter of an internal Procedure/Function.