Parameters & Delegates

Go beyond simple value passing with advanced parameter modifiers and procedural types.

Parameter Modifiers

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.

Lazy Evaluation

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:

  1. If the parameter is never accessed, the expression is never evaluated.
  2. If the parameter is accessed multiple times, the expression is re-evaluated each time.
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);
Result
LOG 1: Status 1
LOG 2: Status 2

Optional Parameters

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
Result
Connecting to localhost on port 80
Connecting to localhost on port 443

Procedural Types (Delegates)

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.

Standard Delegates

Points to a standalone global procedure or function.

type
  TNotifyEvent = procedure(msg: String);

Method Pointers

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);
Result
Button clicked at 10, 20

Anonymous Methods

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.

On this page