var pr: procedure(a, b: real; var res: real);
Переменная называется процедурной если ей можно присваивать процедуры или функции указанного типа.
type BinOpType = procedure(a, b: real; var res: real); var pr: BinOpType; procedure AddOp(a, b: real; var res: real);begin res := a + b;end;procedure MultOp(a, b: real; var res: real);begin res := a * b;end; begin pr := AddOp; var r: real; pr(1,2, r); //вызов процедуры через процедурную переменную pr := MultOp; pr(3,4, r);end. После присваивания процедурной переменной имени процедуры, эта процедура может быть вызвана через переменную:
<имя процедурной переменной>( <список параметров> ); Такой способ вызова процедуры является чрезвычайно гибким, поскольку позволяет менять вызываемое действие в процессе работы программы.
Замечание. До первого присваивания процедурная переменная имеет тип nil. В этот момент вызывать процедуру через переменную нельзя — будет ошибка выполнения.
Функции обратного вызова (callback)
type ActionType = procedure; procedure DoActions(Action1, Action2, Action3: ActionType);begin Action1; Action2; Action3;end; procedure Eat;begin writeln('Студент ест'); end;procedure Think;begin writeln('Студент думает'); end;procedure Sleep;begin writeln('Студент спит'); end; begin DoActions(Sleep, Eat, Sleep); // Первый алгоритм подготовки к сессии DoActions(Think, Eat, Sleep); // Второй алгоритм подготовки к сессии DoActions(Sleep, Sleep, Think); // Третий алгоритм подготовки к сессииend. Процедурные переменные могут являться параметрами других процедур.
При вызове этих процедур им на вход в качестве параметров передаются имена процедур, которые будут вызваны позже внутри основной процедуры. Другими словами, мы передаем в процедуру действие, которое должно быть вызвано (будет вызвано) в определенный момент в этой процедуре.
Такой вызов называется обратным вызовом (callback).
Примечание. Прямой вызов — это передача процедуры в качестве параметра.
Пример. Вычисление определённого интеграла методом прямоугольников.
type func = function(x: real): real;function Integral(a, b: real; N: integer; f: func);begin assert(a < b); var h := (b - a) / N; result := 0; var x := a; for var i := 0 to N-1 do begin Result += f(x); x += h; end; Result *= h;end;