Page 24 - 4800
P. 24

do_answer(X) :- frontchar(X,"< ",Z), colleague(Q,Y), write(" ", Q, " -> ", Y), nl, Q=Z,
            !, fail.
                   /* правило 5 */
                   do_answer(X) :- colleague(X,Y), write(" ", X, " -> ", Y), nl,  fail.
                   Процедура do_answer() складається з п'яти правил. Два з них, перше і п'яте, уже
            були розглянуті раніше.
                   Правило  1  забезпечує  припинення  повтору  запитів  за  рахунок  того,  що  його
            істинність при узгодженні не викликає відкату до предикату repeat.
                   Правило 5 реалізує другу вимогу до запитів і забезпечує видачу всіх товаришів
            по службі конкретного службовця. Розглянемо докладніше інші правила.
                   Правило 2 забезпечує пошук і видачу всіх товаришів по службі за умови, що у
            відповідь на запит про прізвище вводиться слово “all” (тобто всі). Якщо з клавіатури
            введене  будь-яке  інше  значення,  перша  підмета  цього  правила  не  погодиться  і
            виконується відкат, що приводить до подальшого пошуку пропозицій, серед заголовків
            правил процедури do_answer().
                   Якщо  перша  підмета  узгоджується,  то  виконання  другої  підмети  забезпечить
            пошук першої пари колег, а третя підмета забезпечує вивід їх на екран. Предикат fail,
            викликаючи  невдачу,  забезпечує  відкат  до  другої  підмети  для  пошуку  всіх
            альтернативних рішень, що потім виводяться на екран.
                   Розробнику  програми  заздалегідь  відомо,  що  для  обробки  слова  „all”  ніяких
            інших правил у процедурі do_answer не передбачено, але це невідомо системі, і вона
            буде переглядати всі правила процедури і проводити їхню уніфікацію.
                   У  цьому  випадку  має  сенс  обмежити  час  і  простір  пошуку,  закінчивши
            виконання всієї процедури do_answer після обробки слова „all”. З цією метою в дане
            правило  останнім  предикатом  введено  предикат  відсікання,  що  приводить  до
            припинення процедури do_answer, тобто виключенню з подальшого узгодження правил
            3, 4 і 5.
                   Правило  3  реалізує  третю  вимогу  до  запитів,  за  умови,  що  у  відповідь  на
            запрошення  до  вводу,  перед  призвіщем  вводиться,  наприклад,  знак  оклику.  Причому
            вибір початкового символу абсолютно довільний.
                   Нехай,  наприклад,  із  клавіатури  введено  „!Іванов”.  При  узгодженні  заголовка
            правила  3  змінна  Х  уніфікується  з  рядковою  константою  „!Іванов”  і  починається
            обробка тіла правила.
                   Перша  підмета  викликає  стандартний  предикат  frontchar(X,"!",Z)  обробки
            символьних рядків (див. додаток А). Якщо перший символ Х збігається з “!”, то змінна
            Z  приймає  значення  залишку  рядка  X,  починаючи  з  другого  символу  (Z=”Іванов”).
            Якщо перший символ у Х відмінний від “!”, то перша підмета закінчується невдачею і
            відбувається відкат до обробки наступного правила процедури.
                   Друга підмета буде успішна, якщо буде погоджено предикат colleague(Z,_) при
            якому-небудь  значенні  Z.  Використання  анонімної  змінної  обумовлене  характером
            запиту, у якому потрібно визначити тільки наявність колег, а не їхніх прізвищ. Успішне
            узгодження другої підмети викликає перехід до предиката відсікання, що встановлює
            ознаку заборони на відкат в даному місці правила.
                   Після  цього  узгодження  правила  продовжується  праворуч  від  предикату
            відсікання,  і  здійснюється  вивід  на  екран  повідомлення  “Іванов  має  товаришів  по
            службі”.
                   Остання  підмета  викликає  стан  неуспіху  в  доведенні  правила,  що  веде  до
            відкату. Але, тому що предикат write() альтернатив не має, то відбувається відкат до
            предиката  відсікання,  яким  уже  встановлена  заборона  на  подальший  відкат.  Це
            приводить  до  того,  що  на  відміну  від  попередніх  прикладів,  повторне  узгодження
            предикату colleague() виконуватися не буде. На цьому завершується узгодження даного
            правила,  але  не  тільки  його,  але  і  всієї  процедури  do_answer().  Причому  завершення
            процедури  невдачею  веде  до  того,  що  невдачею  завершиться  й  остання  підмета  у
            предикаті  query  і,  як  наслідок,  відбудеться  відкат  до  предикату  repeat  і  повторного
            вводу даних.
                   Дослідіть процес виконання програми при виключенні предикат fail з правила 3.
                   Правило 4 реалізує вимогу на обмеження виведеного списку деякою умовою. Як
            умова виступає прізвище службовця, яким повинний закінчуватися список колег. При







                                                         24
   19   20   21   22   23   24   25   26   27   28   29