Содержание

Использование процедурных типов

Суть этой возможности в Компонентном Паскале состоит в том, что можно создать переменную, которой позже можно присвоить адрес какой-либо процедуры, после чего, можно использовать эту переменную как саму процедуру.

При этом, нужно помнить, что список аргументов у переменной процедурного типа и самой процедуры должны совпадать.

Пример

MODULE FunctionalCalculator;

IMPORT Out := StdLog;

TYPE
  CalculatorLong = PROCEDURE (VAR acc: LONGINT; cur: INTEGER);
  CalculatorBool = PROCEDURE (VAR acc: BOOLEAN; a, b: INTEGER);

PROCEDURE Add(VAR acc: LONGINT; cur: INTEGER);
BEGIN acc := acc + cur END Add;

PROCEDURE Sub(VAR acc: LONGINT; cur: INTEGER);
BEGIN acc := acc - cur END Sub;

PROCEDURE Mul(VAR acc: LONGINT; cur: INTEGER);
BEGIN acc := acc * cur END Mul;

PROCEDURE Div(VAR acc: LONGINT; cur: INTEGER);
BEGIN acc := acc DIV cur END Div;

PROCEDURE Greater(VAR acc: BOOLEAN; a, b: INTEGER);
BEGIN acc := acc & (a > b) END Greater;

PROCEDURE Less(VAR acc: BOOLEAN; a, b: INTEGER);
BEGIN acc := acc & (a < b) END Less;

PROCEDURE ReduceLong(IN nums: ARRAY OF INTEGER; c: CalculatorLong): LONGINT;
VAR
  i: INTEGER;
  acc: LONGINT;
BEGIN
  acc := nums[0];
  FOR i := 1 TO LEN(nums) - 1 DO c(acc, nums[i]) END;
  RETURN acc;
END ReduceLong;

PROCEDURE ReduceBool(IN nums: ARRAY OF INTEGER; c: CalculatorBool): BOOLEAN;
VAR
  i: INTEGER;
  acc: BOOLEAN;
BEGIN
  acc := TRUE; i := 1;
  REPEAT
    c(acc, nums[i-1], nums[i]);
    INC(i);
  UNTIL (i = LEN(nums)) OR ~acc;
  RETURN acc;
END ReduceBool;

PROCEDURE Start*;
VAR
  sn: ARRAY 5 OF INTEGER; (* sn - some nums *)
  orderedNums: ARRAY 3 OF INTEGER;
  sum, mul: LONGINT;
  greater, less: BOOLEAN;
BEGIN
  sn[0] := 1; sn[1] := 3; sn[2] := 5; sn[3] := 7; sn[4] := 9;

  sum := ReduceLong(sn, Add);
  Out.String('sum = '); Out.Int(sum); Out.Ln;

  mul := ReduceLong(sn, Mul);
  Out.String('mul = '); Out.Int(mul); Out.Ln;

  orderedNums[0] := 7;
  orderedNums[1] := 5;
  orderedNums[2] := 1;

  greater := ReduceBool(orderedNums, Greater);
  Out.String('greater = '); Out.Bool(greater); Out.Ln;

  less := ReduceBool(orderedNums, Less);
  Out.String('less = '); Out.Bool(less); Out.Ln;
END Start;

END FunctionalCalculator.

Важные замечания

Если переменной процедурного типа не присвоить значение, она будет иметь значение NIL.