На этом шаге мы рассмотрим раздел доменов.
Домены позволяют задавать разные имена различным видам данных, которые, в противном случае, будут выглядеть абсолютно одинаково. В программах Пролога объекты в отношениях (аргументы предикатов) принадлежат доменам, причем это могут быть как стандартные, так и описанные вами специальные домены.
Раздел domains служит двум полезным целям. Во-первых, вы можете задать доменам осмысленные имена, даже если внутренне эти домены аналогичны уже имеющимся стандартным. Во-вторых, объявление специальных доменов используется для описания структур данных, отсутствующих в стандартных доменах. Иногда очень полезно описать новый домен - особенно, когда вы хотите прояснить отдельные части раздела predicates. Объявление собственных доменов, благодаря присваиванию осмысленных имен типам аргументов, помогает документировать описываемые вами предикаты.
1. Данный пример показывает, как объявление доменов помогает документировать предикаты:
Франк - мужчина, которому 45 лет.
Используя стандартные домены, вы можете так объявить соответствующий предикат:
person(symbol,symbol,integer).
В большинстве случаев такое объявление будет работать очень хорошо. Однако предположим, что несколько месяцев спустя после написания программы, вы решили скорректировать ее. Есть опасение, что подобное объявление этого предиката абсолютно ничего вам не скажет. И напротив, декларация этого же предиката, представленная ниже, поможет вам разобраться в том, что же представляют собой аргументы данного предиката:
domains names,sex=symbol age=integer predicates person (name,sex,age)
Одним из главных преимуществ объявления собственных доменов является то,что Пролог может отслеживать ошибки типов, например, такие:
same_sex(Х,Y):- person(X,Sex,_), person(Sex,Y,_).
Несмотря на то, что и name и sex описываются как symbol, они не эквивалентны друг другу. Это и позволяет Прологу определить ошибку, если вы перепутаете их. Это полезно в тех случаях, когда ваши программы очень велики и сложны.
Почему же мы не можем использовать специальные домены для объявления всех аргументов, если они привносят больше смысла в обозначение аргументов? Ответ заключается в том, что аргументы с типами из специальных доменов не могут смешиваться между собой, даже если эти домены одинаковы. Именно поэтому, несмотря на то, что name и sex принадлежат одному домену symbol, они не могут смешиваться. Однако все собственные домены пользователя могут быть сопоставлены стандартным доменам.
2. Следующий пример программы pro21_1.pro при его загрузке приведет к ошибке типа.
domains product,sum = integer predicates add_em_up(sum,sum,sum) multiply_em(product,product,product) clauses add_em_up(X,Y,Sum):- Sum=X+Y. multiply_em(X,Y,Product):- Product=X*Y.
Эта программа выполняет две операции: складывает и умножает. Зададим ей следующую цель:
add_em_up(32,54,Sum).
Пролог ответит:
sum=86 1 Решение
multiply_em(31,13,Product).
Пролог вернет вам корректный результат:
Product=403 1 Решение
Предположим, что вам понадобилась сумма чисел 42 и 17; цель выглядит так:
add_em_up(42,17,Sum).
А теперь, допустим, вы хотите удвоить произведение 31 на 17. Задаете следующую цель:
multiply_em(31,17,Sum), add_em_up(Sum,Sum,Answer)
Sum=527, Answer=1054 1 Решение
Однако вместо этого вы получите ошибку типа. Это случилось из-за того, что имела место попытка передать результирующее значение предиката multiply_em, которое относится к домену product, в качестве первого и второго аргументов (которые должны относится к домену sum) в предикат add_em_up. Это, собственно, и привело к ошибке, т.к. домен product отличается от домена sum. И хотя оба эти домена соответствуют типу integer - это различные домены.
Поэтому, если переменная в предложении используется более чем в одном предикате, она должна быть одинаково объявлена в каждом из них. Очень важно, чтобы вы поняли концепцию описанной здесь ошибки типа, что позволит избегать сообщений об ошибках компиляции. Различные автоматические и явные преобразования типов, предлагаемые Прологом, будут описаны ниже.
На следующем шаге мы рассмотрим раздел цели.