Это такие типы, с помощью которых можно описать прототипы процедур. И потом объявить процедурные переменные данных типов и вызывать непрямым способом процедуры, на которые они указывают, что позволяет, например, быстро переключать разные реализации процедуры, присваивая процедурной переменной, через которую происходит вызов, других значений. Ближайший аналог из ООП — виртуальные методы классов.
Здесь в коде показано всё. И как описать прототип, и как работать с такой процедурной переменной. Это совершенно реальный и рабочий пример — процедура Is64BitWindows, проверяющая, на 32-битной или 64-битной винде запущена программа:
Код: "OBERON"
(* Copyright (C) 2012-2013 Oleg N. Cher, VEDAsoft Oberon Club *)
MODULE XDevMisc;
IMPORT
SYSTEM, WinApi;
PROCEDURE Is64BitWindows* (): BOOLEAN;
CONST
False = 0;
TYPE
Bool = WinApi.BOOL;
Handle = WinApi.HANDLE;
ISWOW64PROCESS = PROCEDURE(hProcess: Handle; OUT Wow64Process: Bool): Bool;
VAR
IsWow64Process: ISWOW64PROCESS; wow64Process: Bool;
BEGIN
IsWow64Process := SYSTEM.VAL(ISWOW64PROCESS, WinApi.GetProcAddress(
WinApi.GetModuleHandle("Kernel32"), "IsWow64Process"));
RETURN (IsWow64Process # NIL)
& (IsWow64Process(WinApi.GetCurrentProcess(), wow64Process) # False)
& (wow64Process # False)
END Is64BitWindows;
END XDevMisc.
Если бы мы вызывали процедуру IsWow64Process статически, то могли бы прогореть на том, что она присутствует не в каждой версии Kernel32, о чём предупреждает Microsoft. В этом случае наша программа отвалилась бы со страшным сообщением типа: "Точка входа в процедуру IsWow64Process не найдена в библиотеке kernel32.dll". Динамически же мы сперва проверяем, существует ли точка входа в эту процедуру. И только потом, если да, вызываем её. А если нет, то делаем предположение, что винда таки не 64-битная.
Работа с процедурными переменными имеет смысл не только в системном программировании. В прикладной области этому подходу тоже можно найти применение. А вот что говорит документация ББ по данному вопросу:
Docu/ru/CP-New писал(а):
Процедурные типы
Процедурные типы обладают меньшей гибкостью, чем объекты с методами. Даже в обычных примерах использования процедурных типов в ПО для числовых расчетов можно получить выигрыш, моделируя их посредством объектов. Объекты расширяемы, а процедурные типы — нет. Процедурные типы могут создавать значительные трудности для безопасной выгрузки модулей. Пока что они сохранены для обратной совместимости, а также для реализации низкоуровневого интерфейсного кода (обратные вызовы, callbacks). В перспективе поддержка процедурных типов может быть уменьшена.
Почему так? Потому что в компонентной среде с динамической загрузкой/выгрузкой модулей "на лету" есть проблемы с процедурными переменными, когда модуль, реализующий процедуру, на которую указывает переменная, уже выгружен, а программист процедуру вызвал (и потерпел крах). Поэтому парни из Oberon Microsystems советуют вместо процедурных переменных использовать методы объектов.