2013-05-01 2 views
3

В книге нам предлагается определить предикаты left_of, right_of, выше и ниже, используя следующий макет.left_of упражнения из Art Of Prolog

% bike    camera 
% pencil hourglass butterfly fish 

left_of(pencil, hourglass). 
left_of(hourglass, butterfly). 
left_of(butterfly, fish). 

above(bike, pencil). 
above(camera, butterfly). 

right_of(Obj1, Obj2) :- 
    left_of(Obj2, Obj1). 

below(Obj1, Obj2) :- 
    above(Obj2, Obj1). 

Это похоже на правильные решения.

Позже в книге нам предлагается добавить рекурсивное правило для left_of. Единственное решение, которое я смог найти, это использовать другое имя функтора: left_of2. Поэтому я в основном переопределял отношения между предками.

left_of2(Obj1, Obj2) :- 
    left_of(Obj1, Obj2). 
left_of2(Obj1, Obj2) :- 
    left_of(Obj1, X), 
    left_of2(X, Obj2). 

В своих попытках повторного использования left_of, я могу получить все правильное решение, но на конечном повтор, происходит переполнение стека. Я предполагаю, что это потому, что у меня нет правильного базового аргумента. Может ли это быть закодировано с использованием left_of для фактов и рекурсивной процедурой?

+0

Действительно? Кажется, он работает правильно. Возможно, вы захотите выйти из сеанса Prolog и снова загрузить код, чтобы убедиться. –

+0

Даниэль, мой вопрос можно было использовать для фактов и рекурсивного правила (без использования left_of2). Возможно, я неправильно интерпретирую упражнение. – stirfoo

+1

В этом случае ответ отрицательный. В Prolog есть много случаев, когда у вас должны быть отдельные предикаты, где вам не нужны они на других языках (на ум приходят также петли с шагами инициализации или финализации). Это всего лишь один из них. Вы всегда можете скрыть «внутренний» предикат с другим именем ('direct_left_of/2' приходит на ум) и выставить' left_of2' как 'left_of' для ваших пользователей. –

ответ

5

Как уже упоминалось в комментариях, это печальный факт, что в Prolog вы должны иметь отдельные предикаты для этого. Если вы этого не сделаете, вы будете заводить с чем-то, что выглядит следующим образом:

left_of(X,Z) :- left_of(X,Y), left_of(Y,Z). 

, который дает вам неограниченную рекурсию дважды. Нет ничего плохого в принципе с фактами и предикатами, использующими одно и то же имя - на самом деле, это довольно обычное правило для базового случая, чтобы выглядеть как факт. Дело в том, что обработка транзитивной ситуации закрытия, подобная этой, приводит к переполнению стека, если один из двух шагов не является конечным, и нет другого способа гарантировать, что в Prolog, чем путем их именования отдельно.

Это далеко не единственный случай в Прологе, где вы вынуждены разбивать работу на отдельные предикаты. Другие часто встречающиеся случаи включают в себя вычислительные циклы с инициализаторами или финализаторами.

Обычно можно было бы называть предикат иначе, чем факт. Например, directly_left_of для фактов и left_of для предиката. Используя систему модулей или Logtalk, вы можете легко скрыть «прямую» версию и побудить своих пользователей использовать переходную версию. Вы также можете сделать намерение более явным, не запрещая его, используя неудобное имя для скрытого, например left_of_.

На других языках функция представляет собой более непрозрачную, более крупную абстракцию, и есть возможности для скрытия значительной работы за ней. Предикаты Пролога, для сравнения, «более простые», которые меня беспокоили. В настоящее время я рад, что они проще, потому что есть много других вещей, которые я получаю, я рад, что мне также не нужно вычислять предикаты переменной или аргументы ключевых слов (хотя вы можете легко имитировать оба списка, если вы нужно).

+0

Спасибо, Даниил за это объяснение. Пролог - самый сложный язык, который я пытался сделать до сих пор.(схема, cl, clojure, python, C++ и C) – stirfoo

+0

Сначала это невероятно странно, и становится все лучше и веселее, но остается странным. :) Я рад, что вы даете ему шанс, и вы читаете классическую книгу, которая поможет очень, как и ваш фон FP. Я рад, что могу помочь, и не стесняйтесь писать мне по электронной почте. –

Смежные вопросы