פרולוג מצליח להסיק שיוסי קורא את כל ספרי הפנטזיה בתכנית מלבד ספרי הארי פוטר:
?- reads1(yossi, harry_potter).
No
?- reads1(yossi, the_hobbit).
Yes
?- reads1(yossi, the_lord_of_the_rings).
Yes
?- reads1(yossi, alice_in_wonderland).
Yes
הפתרון שהצגנו עובד, אבל הוא עובד בהסתמך על תכונות פרוצדורליות של פרולוג. אם נהפוך את סדר החוקים המתארים את העדפותיו של יוסי או נסיר את ה-cut, נקבל תוצאות שגויות.
עלינו למצוא דרך טובה יותר להביע את העובדה שיוסי לא קורא ספרים מאת ג'יי קיי רולינג. כלומר, עלינו למצוא דרך טובה יותר להביע שלילה. נשתמש בצירוף cut-fail, אבל נעטוף אותו במתאר מיוחד שיביע שלילה: lo (מלשון לא). שימוש בצירוף תכונות זה על מנת להביע שלילה נקרא שלילה על ידי כשלון (negation as failure).
lo(X) :- X, !, fail.
lo(X).
אם X מתקיים, אז נכשלים, ו-lo(X) נכשל. אם X לא מתקיים, החוק השני מצליח ומתקיים lo(X).
גרסא משופרת של הרגלי הקריאה של יוסי עושה שימוש במתאר lo:
reads2(yossi, X) :- fantasy(X), lo(author(X, j_k_rowling)).
למעשה פרולוג מכיל מתאר מערכת שמשמעותו בדיוק כמו זו של lo: +\. זהו אופרטור prefix שמשמעותו שלילה על ידי כשלון:
?- \+ reads2(yossi,harry_potter).
Yes
מילה של אזהרה:
למרות שהאופרטור +\ משמש אותנו להביע שלילה, הוא איננו שקול לאופרטור השלילה בלוגיקה. בלוגיקה הטענות "p וגם לא-q" ו- "לא-q וגם p" שקולות. לעומת זאת, בפרולוג יש חשיבות למיקום השלילה בתוך הגימום. בהגדרת reads2 הקפדנו לרשום את טענת השלילה בסוף הגימום. נגדיר reads3 שבו השלילה בהתחלה:
reads3(yossi, X) :- \+ author(X, j_k_rowling), fantasy(X).
כאשר אנו מנסים לקבל את רשימת הספרים שיוסי קורא, פרולוג עונה לנו תשובה תמוהה:
?- reads3(yossi,Book).
No
זו גם תשובתו בגרסא הראשונה, reads1. מה קורה כאן? פרולוג מצליח להוכיח את המטרה author(X, j_k_rowling) (על ידי האחדה בין X לבין harry_potter) ולכן נכשל בהוכחת שלילת הטענה. מכיוון שנכשל בהוכחת החלק הראשון של הגימום, הוא נכשל בהוכחת הגימום כולו, ועונה No. בגרסא השנייה, reads2, אנחנו קודם מציבים ערך ב-X ורק אז בודקים אותו. זו הדרך בה צריך לכתוב בפרולוג על מנת לקבל את ההתנהגות הנכונה:
?- reads2(yossi,Book).
Book = the_hobbit ;
Book = the_lord_of_the_rings ;
Book = alice_in_wonderland ;
No
|