Records

Records are structured types that group related data together. In DWScript, they are powerful value types that support methods and operator overloading.

Basic Records

In its simplest form, a record is a set of data fields. It maps directly to a block of memory.

type
  TPoint = record
    X, Y: Integer;
  end;

var p: TPoint;
p.X := 10;
p.Y := 20;

Fields in a record are public by default.

Default Field Values

You can specify default values for fields in a record. These values are applied when the record is initialized. Type inference is also supported.

type
  TSettings = record
    Width: Integer := 800;
    Height := 600; // Type inferred as Integer
    Name: String := 'Untitled';
  end;

var s: TSettings;
PrintLn(s.Width);
PrintLn(s.Height);
PrintLn(s.Name);
Result
800
600
Untitled

Anonymous Records

Anonymous records allow you to define and initialize a record in a single expression, similar to JSON objects. They are fully compatible with System.JSON.

var user := record
  id := 123;
  name := 'Alice';
  &type := 'Admin';  // '&' allows using reserved words like 'type'
end;

PrintLn(user.name); 
PrintLn(user.&type);
Result
Alice
Admin

JSON Compatibility

Anonymous records are highly compatible with JSON.Stringify. In DWScript, anonymous records have their fields in a published section by default, ensuring they are automatically included during serialization.

The & prefix is also handled during serialization, so &type becomes "type" in the resulting JSON.

For more details, see JSON Support.

Advanced Features

Unlike standard Pascal records, DWScript records can have visibility specifiers, methods, and properties.

type
  TVec2 = record
  private
    FX, FY: Float;
  public
    procedure SetPos(x, y: Float);
    function Length: Float;
    property X: Float read FX;
    property Y: Float read FY;
  end;

procedure TVec2.SetPos(x, y: Float);
begin
  FX := x; FY := y;
end;

function TVec2.Length: Float;
begin
  Result := Sqrt(FX*FX + FY*FY);
end;

var v: TVec2;
v.SetPos(3, 4);
PrintLn(v.Length.ToString);
Result
5

Value Semantics

Records are value types. This means they are copied when assigned to a new variable or passed to a function (unless using var). They do not support inheritance.

type
  TPoint = record
    X, Y: Integer;
  end;

var a, b: TPoint;
a.X := 10;

// b gets a copy of a's value
b := a;

// Modifying b does not affect a
b.X := 20;

PrintLn('a.X = ' + a.X.ToString);
PrintLn('b.X = ' + b.X.ToString);
Result
a.X = 10
b.X = 20

Methods & Operators

Records can have methods and operators, allowing them to behave like light-weight objects while retaining value semantics.

Pseudo-Constructors

While records do not support traditional constructor syntax, you can use a class function to create a factory method (pseudo-constructor).

type
  TMyVector = record
    X, Y: Float;
    class function Create(aX, aY: Float): TMyVector;
    begin
       Result.X := aX;
       Result.Y := aY;
    end;
  end;

var v := TMyVector.Create(10, 20);
PrintLn(v.X.ToString + ', ' + v.Y.ToString);
Result
10, 20

Operator Overloading

Records can define operators like +, -, or implicit and explicit casts.

type
  TVec2 = record
    X, Y: Float;
    class function Create(aX, aY: Float): TVec2;
    begin
       Result.X := aX;
       Result.Y := aY;
    end;
  end;

function AddVec2(a, b: TVec2): TVec2;
begin
   Result.X := a.X + b.X;
   Result.Y := a.Y + b.Y;
end;

// Overload the + operator
operator + (TVec2, TVec2): TVec2 uses AddVec2;

var v1 := TVec2.Create(10, 20);
var v2 := TVec2.Create(5, 5);
var v3 := v1 + v2;

PrintLn(v3.X.ToString + ', ' + v3.Y.ToString);
Result
15, 25

Implicit Operators

DWScript supports Implicit Operators, which allow for automatic type conversion between records and other types. This is useful for creating types that behave like primitives.

type
  TMoney = record
    Amount: Float;
    Currency: String;
  end;

function FloatToMoney(f: Float): TMoney;
begin
  Result.Amount := f;
  Result.Currency := 'USD';
end;

// Enable automatic conversion from Float to TMoney
operator implicit (Float): TMoney uses FloatToMoney;

var wallet: TMoney;
wallet := 50.0; // Automatically calls FloatToMoney

PrintLn(wallet.Amount.ToString + ' ' + wallet.Currency);
Result
50 USD
On this page