Диапазоны так диапазоны, контракты так контракты.
Разница в том, что диапазон он для данных. И там вообще может быть не диапазон. Диапазон он в примере представлен. Одни и те же данные для разных функций должны удовлетворять разным условиям. Точней не всегда должны, а могут вообще говоря. Снова вспомним арифметику - функция для сложения например принимает целые числа. Для деления не включат ноль. Данные остались прежние, что тип поменялся? А здесь перед вызовом функции идет проверка предусловия, что деление не может иметь аргументом ноль (сами данные нулем могут быть для других функций).
Вот пример две функции в калькуляторе:
1) Function Adder(x, y: Integer): Integer;
2) Function Divider(x, y: Integer): Integer;
Очевидно что тип Integer совершенно не решает проблему Divider для аргумента у. Ваши предложения? Завести еще один тип? Integer без нуля? То есть потенциально Integer в данном примере источник ошибок и контроль типов не решает проблему деления на нуль. И второй косяк в печатании:
Memo1.Lines.Add('Результат: '+IntToStr(x));
Разве в алгоритме калькулятора где-то есть преобразование типа? Нет, это особенность реализации. Я понимаю, что и мое видение не решает многих проблем, но оно должно уменьшить количество преобразований.
Могут ли там быть переменные значения?
В смысле? Я не совсем понял вопроса, дайте пример как Вы хотите. Диапазон в примере это и есть имя функции-предиката, не ключевое слово. Назовите по-другому. Или Вы хотите косвенную адресацию? Я думал об этом вскользь. Для функций такая фишка должна быть, типа вызвать функцию по содержимому строки. Так как предикат это разновидность функции, на нее должны распространяться эти правила. И второе - функция это система, а системы можно переименовывать. Следовательно, Вы можете поступить так - передать в функцию более высокого уровня параметром предикат, переименовать его так как Вам нужно и скормить его для вызова.
Ну например, есть функции а, б, в и предикат г.
В функции б требуется отследить работу функции в (допустим, что бы результат в соответствовал условиям г). Тогда функция а, в зависимости от каких-то условий передает предикат д (а может е, а может ё) в функцию б. Функция б переименовывает ё в г и отслеживает вызов функции в. Функция в исполняется и ее результат сравнивается с в. При этом в может быть и д и е и ё и т.д.
Я не знаю насколько это практично само по себе. Просто такая возможность есть, она предоставляется системам. При добавлении некоторых простейших механизмов можно даже сделать так, что в ряде случаев даже порядок расположения параметров будет не важен. Можно будет сравнивать по типу. Например, через foreach пройтись по параметрам и если он предикат, переименовать его в г (а если нет, значит генерить ошибку или использовать какой-то свой, может пустой предикат, который всегда True. Ну или что-то типа того.
Конечно, когда нужно два предиката, отличить их будет сложней. Но если предикат один, а остальное прочие данные, то в принципе все равно каким он передан в функцию в качестве первого параметра или второго. То есть при правильном проектировании сам порядок расположении входящих параметров в функции теряет смысл.
Есть такая простая идея - при старте функции она получает две подсистемы параметры и результат. Так как это будет использоваться очень часто можно обозвать их как-нибудь. Допустим минус это параметры (удобно - не нужно переключать раскладку и всего один символ), а плюс это результат функции.
В параметры копируется все что туда передали в качестве подсистем в том порядке в каком они там следуют. Соответственно для их пакетной обработки нужен только foreach. Дальше определяем природу системы и работаем. Смысл в том, что если точно известно что перед нами, то не важно как оно располагается в аргументах. Пока коряво, но как-то так.
Это также открывает ряд мелких плюшек - например, написать функцию по лисповски с произвольным числом параметров (тут только нужно очень тщательно проработать синтаксис). Типа Сложить (1, 2) или Сложить (1, 2, 3, 4). Если передавать параметры как описано выше тем же Foreach можно без проблем одним кодом складывать хоть один аргумент, хоть тысячу (правда в этом тоже нет особого смысла - ведь все параметры можно просто засунуть в одну надсистему и передавать уже ее).