Метод повтора, определяемый пользователем (МП)

Правило повтора имеет вид:

repeat.

repeat:-repeat.

Правило, которое использует само себя как компоненту (третий repeat). Второй repeat вызывает третий repeat, и этот вызов всегда успешен, так как первый repeat удовлетворяет подцели repeat, следовательно, правило repeat также всегда успешно.

Предикат repeat будет вычисляться успешно при каждой новой попытке его вызвать после отката.Repeat используется в качестве компоненты других правил.

Листинг 5.7. Использование repeat для ввода и вывода на экран символов до тех пор пока не будет нажата клавиша ‘Enter’.(ASCII-код =13)

predicates

repeat

typewriter

clauses

repeat.

repeat:-

repeat.

typewriter:-

repeat,

write(“ input char”),nl,

readchar(Ch),

write(Ch),nl,

char_int(Ch,13),

write(“end”).

goal:typewriter,nl.

Встроенный предикат readсhar(Ch) читает новое значение, вводимое с клавиатуры только при первом вызове предиката и не делает этого при возврате (то есть если использовать здесь предикат fail, то повтора чтения не произойдет):

typewriter:-

readchar(Ch),

write(Ch),

fail.

Встроенный предикат repeat позволяет преодолеть эту трудность. Однако даже repeat при наличии fail не приведет к завершению программы, потому что комбинация repeat…..fail приводит к бесконечному циклу:

typewriter:-

repeat,

readchar(Ch),

write(ch),

fail.

Как выйти из комбинации repeat…fail? Очевидно, необходимо ввести индикатор завершения программы и заменить им предикат fail. Таким индикатором в нашей ситуации является нажатие на клавишу ‘Enter’.Для этого можно использовать стандартный предикат char_int(CharParam,IntParam), который успешен, если код символа CharParam совпадает со значением IntParam.

Листинг 5.8.Использование метода повтора для ввода двух новых чисел и получения их суммы.

predicates

sum(integer,integer,integer)

repeat

summa

check(integer,integer)

write_message

goal

clearwindow,

write_message,

summa.

clauses

repeat.

repeat:-

repeat.

write_message:-

nl,write(”input 2 integer number”),nl,

write(“for stop input 0 for X or Y”),nl,nl.

summa:-

repeat,

write(“input X=”),

readint(X),nl,

write(“input Y=”),

readint(Y),nl,

write(“X=”,X,” Y=”,Y),nl,

check(X,Y),!.

check(X,0):-

nl,write(“OK”).

check(Y,0):-

nl,write(“OK”).

check(X,Y):-

sum(X,Y,Z),

write(“ Z=”,Z),nl,

write(“input new integer”),nl,

write(“ numbers for X and for Y”),nl,

fail.

sum(X,Y,Z:-

Z=X+Y.

В данной программе для останова процесса сложения вместо одного из двух чисел(или вместо и того и другого) вводится 0.

Следует помнить, что:

-предикаты read и write читают и печатают свои значения только при первом вызове, поэтому fail здесь не поможет, а repeat будет на месте;

- правило repeat дает бесконечные циклы, поэтому нужен признак конца;

- все переменные теряют свои значения при откате обработки в позицию, предшествующую тем вызовам предиката, который эти значения устанавливал.

Замечания.

· Если необходимо бесконечное выполнение, и окончание наступает только при возникновении каких- то исключительных ситуаций, то в не интерактивных программах можно использовать предикат exit, прекращающий выполнение программы. В интерактивных программах можно нажать клавишу <Break>.

· Так как ни write(), ни readchar() не являются альтернативными, то возврат происходит к repeat,который всегда имеет альтернативные решения.

· Обратите внимание на то, что Ch теряет свое значение после отката в позицию перед вызовом предиката readchar(Ch), который связывает переменную Ch.Такой тип освобождения переменной важен, когда поиск с возвратом применяется для определения альтернативных решений, но он не эффективен при использовании поиска с возвратом в других целях. Суть в том, что хотя поиск с возвратом и может повторять операции сколько угодно раз, но он не способен “запомнить” что-либо из одного повторения для другого. Поэтому write() надо сделать перед повтором, так как вы теряете при откате значение переменной.

· Правило repeat позволяет получить бесконечные откаты. В МП откат может быть выполнен всегда в отличии от метода ОО, где откат выполняется только после искусственно созданного неуспешного результата. Но не следует забывать о необходимости введения признака завершения повторов.

Выводы

1. Предикат fail вызывает неуспшное завершение правила, заставляя внутренние унификационные программы выполнять откат, а процесс повторяться до тех пор, пока не будет обработано последнее утверждение.

2. Оператор отсечения cut предотвращает перебор с возвратами, не давая проверять альтернативные цели, если заранее известно, что они все равно окончатся неудачей.

3. Оператор отсечения позволяет сформулировать взаимоисключающие утверждения с помощью правил вида: если Условие, то Заключение 1,иначе Заключение 2.

4. Оператор отсечения позволяет сделать процедуру детерминированной.

5. Оператор отсечения может нарушить соответствие между декларативным и процедурным значениями программы, поэтому надо быть предельно осторожным при его использовании.

6. Оператор not как недостижение цели не полностью соответствует понятию отрицания в математике, поэтому и при работе с ним также требуется определенная осторожность.

7. Правило повтора repeat успешно при каждой новой попытке вызвать его после отката.

Эффективен при реализации доступа к данным в базе данных и файлах на диске. Используется для формирования меню и выдачи его на экран.


Понравилась статья? Добавь ее в закладку (CTRL+D) и не забудь поделиться с друзьями:  



double arrow
Сейчас читают про: