Records are structured types that group related data together. In DWScript, they are powerful value types that support methods and operator overloading.
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.
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); 800 600 Untitled
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); Alice Admin
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.
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); 5
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); a.X = 10 b.X = 20
Records can have methods and operators, allowing them to behave like light-weight objects while retaining value semantics.
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); 10, 20
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); 15, 25
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); 50 USD