פרק 7: עוד על ביטויים7.1 ניתוח מבנה הביטוי |
עוד בפרק הראשון למדנו על סוגי הביטויים בפרולוג.
כעת נלמד על מתארי-מערכת בפרולוג שתפקידם לזהות סוגי ביטויים, ולפרק אותם למרכיביהם. יכולת זו עשויה להיות שימושית לנו אם עלינו להתייחס בתכנית לסוגי ביטויים שונים, ולטפל בצורה ייחודית בכל אחד מהם.
זיהוי סוג הביטוי
המתארים הבאים מזהים את סוגי הביטויים השונים:
עקבו אחר תשובותיו של פרולוג (הסברים תוכלו למצוא על ידי הצבעה עם העכבר):
?- atomic(1).
Yes
?- atomic(one).
Yes
?- atomic(One).
No
?- atomic(1+1).
No
?- number(1*9).
No
?- var(V).
V = _G179
Yes
?- V=3, var(V).
No
?- V=3, nonvar(V).
V = 3
Yes
?- var(V), V=3.
V = 3
Yes
אופרטורים הם ביטויים מורכבים, זוכרים? |
המתואר כאן הוא ביטוי מורכב ולא מספר (סוג של ביטוי פשוט). |
המשתנה V איננו מאותחל, לכן פרולוג משיב בחיוב. |
הפעם פרולוג משיב בשלילה כי הצבנו ערך במשתנה. |
זו השאלה ההפוכה, והתשובה חיובית. |
יש כמובן חשיבות לסדר: אם נשאל לפני האתחול, ישיב פרולוג בחיוב. |
שימו לב לקוד האינטראקטיבי.
|
מתארים שמחזירים מתאר ושדה
פרולוג מאפשר לנו לקבל מידע מפורט על מבנה ביטויים מורכבים. בהינתן ביטוי מורכב, ניתן לברר מהו המתאר הראשי בביטוי, ומהו השדה שלו (שדה הוא מספר המתוארים של המתאר). עושים זאת בעזרת המתאר functor, המוגדר כדלקמן:
functor(?Term, ?Functor, ?Arity)
Succeeds if Term is a term with functor Functor and arity Arity.
If Term is a variable it is unified with a new term holding only
variables. functor/3 silently fails on instantiation faults if Term is an atom or
number, Functor will be unified with Term and
arity will be unified with the integer 0 (zero).
|
פעולתו על ביטוי מורכב:
?- functor(3+3,Functor, Arity).
Functor = +
Arity = 2
Yes
פעולתו על ביטוי פשוט:
?- functor(3,Functor, Arity).
Functor = 3
Arity = 0
Yes
כמו שראינו כשבנינו מתארי רשימות, גם כאן ניתן להשתמש במתאר כדי לבנות ביטויים מורכבים חדשים, לא רק כדי לברר מה מבנם של ביטויים מורכבים קיימים. הנה דוגמא:
?- functor(Term, $, 3).
Term = $(_G318, _G319, _G320)
Yes
בנינו ביטוי מורכב ממתאר $ עם שלושה מתוארים.
שימושים ב-functor, הם אם כך שניים:
- קבלת מידע על מבנה ביטוי נתון
- הגדרת מתארים של ביטויים מורכבים
דוגמא
נגדיר מתאר בשם yoce שמגלה פעלים יוצאים. פועל יוצא הוא פועל שיש לו משלים אחד לפחות, למשל: חבר (ספר), קנה (ארון) (השווה עם: רץ, נפל, התקלח).
נניח שהמידע על פעלים מיוצג כדלקמן:
rac.
yashan.
nafal.
xiber(sefer).
kana(aron).
שימו לב לקוד האינטראקטיבי.
נוכל לזהות את הביטויים המורכבים כך:
yoce(Poal) :-
nonvar(Poal),
functor(Poal, _, Arity),
Arity > 0.
המתאר שכתבנו אמנם מצליח לזהות פעלים יוצאים:
?- yoce(rac).
No
?- yoce(kana(sefer)).
Yes
?- yoce(natan(sefer, le-dina)).
Yes
|
מתאר נוסף מאפשר לנו לגשת אל אחד המתוארים כרצוננו, או לאתחל את ערכו. זהו המתאר arg/3:
arg(?Arg, ?Term, ?Value)
Term should be instantiated to a term, Arg to an integer between
1 and the arity of Term. Value is unified with the Arg-th
argument of Term. Arg may also be unbound. In this case Value
will be unified with the successive arguments of the term. On
successful unification, Arg is unified with the argument number.
Backtracking yields alternative solutions. The predicate arg/3
fails silently if Arg= 0 or Arg > arity and raises the exception
domain_error(not_less_then_zero, Arg) if Arg <0.
|
פעולתו כדלקמן:
?- arg(2,abra(kadabra, hokus_pokus),Arg).
Arg = hokus_pokus
Yes
?- arg(2,abra(kadabra, X),stagada).
X = stagada
Yes
לבסוף נכיר את האופרטור 2/'..=' (נקרא גם univ). זה משמש אותנו לפרק (או להרכיב!) ביטוי מורכב למתאר ומתוארים, אשר ניתנים כאברים ברשימה. ראשית, דוגמא לפירוק:
?- abra(kadabra, 1, 2, Y) =.. List.
Y = _G335
List = [abra, kadabra, 1, 2, _G335]
Yes
ודוגמא להרכבה:
?- Term =.. [abra, kadabra, 1,2,Z].
Term = abra(kadabra, 1, 2, _G344)
Z = _G344
Yes
הערה על יעילות: מכיוון ש-univ בונה רשימה מתוך מבנה, הוא לא יעיל במיוחד. לכן, אם מטרתכם היא לגשת לחלק מסוים של המבנה, עדיף להשתמש ב-arg/3.
שימוש ב-..= מאפשר לנו לגשת למתאר ולכל המתוארים בביטוי מורכב. נוכל בעזרתו לבצע פעולות כמו שינוי שמות מתוארים, יצירת העתקים של ביטויים, וכל פעולה אחרת שדורשת גישה למרכיביו של הביטוי.
|
|
מבוא |
|
נושאים בסיסיים |
|
נושאים מתקדמים |
|
סיכום |
|
|