Go beyond simple value passing with advanced parameter modifiers and procedural types.
How a value is passed to a subroutine significantly affects both performance and behavior.
| Modifier | Description |
|---|---|
| (none) | Value: A copy of the value is passed. Changes inside the subroutine do not affect the original. |
var |
Reference: A pointer to the original variable is passed. Changes inside affect the original. |
const |
Constant: Passed by reference for efficiency, but the compiler prevents modification. |
lazy |
Lazy: The expression is only evaluated when accessed inside the body. This is useful for conditional logic or logging. |
The lazy modifier is a unique feature of DWScript that defers the evaluation of an expression passed as a parameter until the moment it is actually accessed within the subroutine body.
Key behavior:
procedure LogIf(condition : Boolean; lazy message : String);
begin
if condition then begin
// 'message' is evaluated here
PrintLn('LOG 1: ' + message);
// ...and re-evaluated here!
PrintLn('LOG 2: ' + message);
end;
end;
var counter := 0;
function GetStatus : String;
begin
Inc(counter);
Result := 'Status ' + IntToStr(counter);
end;
// GetStatus is NOT called here
LogIf(False, GetStatus);
// GetStatus IS called (twice!)
LogIf(True, GetStatus); LOG 1: Status 1 LOG 2: Status 2
You can define default values for parameters. Optional parameters must always appear at the end of the parameter list.
procedure Connect(host : String; port : Integer = 80);
begin
PrintLn('Connecting to ' + host + ' on port ' + IntToStr(port));
end;
Connect('localhost'); // Uses port 80
Connect('localhost', 443); // Uses port 443 Connecting to localhost on port 80 Connecting to localhost on port 443
Procedural types allow you to treat subroutines as first-class citizens. You can assign them to variables, store them in arrays, or pass them as parameters to other subroutines.
Points to a standalone global procedure or function.
type
TNotifyEvent = procedure(msg: String); In DWScript, the of object syntax allows you to point to a method of a specific object instance. When the delegate is called, it executes the method in the context of that object.
type
TClickEvent = procedure(x, y : Integer) of object;
type
TButton = class
OnClick : TClickEvent;
procedure Click(x, y : Integer);
begin
if Assigned(OnClick) then OnClick(x, y);
end;
end;
type
TForm = class
procedure ButtonClicked(x, y : Integer);
begin
PrintLn('Button clicked at ' + IntToStr(x) + ', ' + IntToStr(y));
end;
end;
var f := new TForm;
var b := new TButton;
b.OnClick := f.ButtonClicked;
b.Click(10, 20); Button clicked at 10, 20
For one-off logic, you can use anonymous methods (lambdas) which can capture local variables from their surrounding scope. See the Lambdas page for more details.