prepd.אתר תרגול לבחינות
איך ללמודצור קשר
© 2026 prepd. כל הזכויות שמורות.·אודות·תנאי שימוש·מדיניות פרטיות·נגישות

שפות תכנות האוניברסיטה הפתוחה

תכנות פונקציונלי, מודל הסביבה, זרמים, תכנות לוגי ומערכות טיפוסים

סטטיסטיקות מבחנים
כדי לגשת למבחני סימולציה ועוד המון שאלות נוספות, פתחו גישה מלאה
רמת קושי:
לפניך תוכנית בשפת Implicit-Refs (שפת ייחסמוריות):



מה הניב התוכנית הזו?

א. (num-val 12)

ב. (num-val 9)

ג. התוכנית מחזירה שגיאה בזמן הריצה.

ד. (num-val 11)

ה. (num-val 2)

ו. (num-val 4)

ז. (proc-val ...)

סמן את התשובה הנכונה ורשם במחברת הבחינה בלנד.
העתק שאלה
שתף שאלה
סמן כחשוב
סמן כבוצע
האוניברסיטה הפתוחהמועד ג · 2024 · סמסטר ב
★★★★★
מפרשיםמצבמעקב אחר קודScheme
להלן תוכנית בשפת PROC ("יישגור"):



תוצאת הריצה של תוכנית זו היא:

א. proc-val

ב. (num-val 6)

ג. (num-val 5)

ד. (bool-val #t)

ה. (bool-val #f)

ו. התוכנית מחזירה שגיאה בזמן הריצה.

נמקו והסבירו את תשובתכם ע"י הסבר דרך חישוב תוצאת התוכנית. את תשובתכם רשמו במחברת הבחינה בלבד.
העתק שאלה
שתף שאלה
סמן כחשוב
סמן כבוצע
האוניברסיטה הפתוחהמועד ב · 2024 · סמסטר ב
★★★★★
Schemeתכנות פונקציונלימודל הסביבהמעקב אחר קודlet
להלן תוכנית בשפת PROC (שפת "יירשגורי"):



הוצגת התוצאה של התוכנית הנ"ל היא:

א. (num-val 12)
ב. (num-val 18)

ג. (num-val 6)

ד. (num-val 9)

ה. התוכנית לא תקינה ותיכשל

ו. התוכנית מחזירה שגיאה בזמן הריצה.


יש לבחור את התוצאה הנכונה מתוך האפשרויות לעיל, ולנמק בדרך של הצגת חישובים והוכחות. את התשובה יש לנמק בלבד.
העתק שאלה
שתף שאלה
סמן כחשוב
סמן כבוצע
האוניברסיטה הפתוחהמועד א · 2024 · סמסטר ב
★★★★★
מודל ההצבהמעקב אחר קודSchemeתכנות פונקציונליסגוריםתחום לקסיקלי
בשאלה זו נוסיף לשפת PROC ("יישגור") מרכיב חדש בשם overload proc.

התחביר החדש הוא:

Expression ::= overload proc [ [identifier]* -> Expression ; ]+ 


עם בנאי: overload-proc-exp(ids, bodies)

וכן:

Expression ::= (Expression | Expression }+)


עם בנאי: call-exp(rator, rands)

מרכיב ה-overload proc מגדיר פרוצדורה בשם p שלה מספר גרסאות. כל גרסה כוללת כמות פרמטרים שונה וגוף פרוצדורה שונה לביצוע. הגרסה הראשונה כוללת 2 פרמטרים, הגרסה השנייה היא כפרוצדורה ללא פרמטרים, והגרסה השלישית היא של פרוצדורה בעלת פרמטר יחיד. בגוף פעולת ה-let מופעלת הפרוצדורה p עם 2 פרמטרים, וזה מתאים לגרסה הראשונה שלה, ולכן מבוצעת פעולת החיסור בין הפרמטרים.

להלן דוגמאות להמחשת אופן השימוש במרכיב החדש:

דוגמה 1:



דוגמה 2:



דוגמה 3:



דוגמה 4:



דוגמה 5:



ממשו והטמיעו את השינויים הדרושים כפי שהוגדרו והודגמו בתוך שפת "יישגור" (שפת PROC).

בתשובתכם, הקפידו להסביר היכן בדיוק נדרשים שינויים ותוספות בקבצי המפרש, ומהם השינויים והתוספות.

הנחיות כלליות לפתרון:
1. הקפידו על כתב ברור, ועל קוד מבני ומסודר.

2. הקפידו על פתיחת וסגירת סוגריים במקומות הנכונים.

3. הפתרון אמור לשמור על הגדרות השפה המקוריות (פרט למקרים בהם נדרש שינוי כפי שמפורש בשאלה).

4. על מנת לפשט קוד ארוך, כדאי ורצוי להיעזר בכתיבת פרוצדורות עזר (מחוץ ל-value-of או כאלה המוטמעות בתוכו).

5. בפתרונכם, הקפידו על אבחנה ושימוש נכון בין ביטוי (expression) לבין תוצאת חישוב ביטוי (expval) לבין identifier.


ניקוד יורד על אי ניתוח ומימוש נכון של הדקדוק הנתון בשאלה, כלומר יש להפקיד על זיהוי וטיפול נכון ב- terminals, non-terminals ופעולות של סגור ( ), { }*, { }+.
העתק שאלה
שתף שאלה
סמן כחשוב
סמן כבוצע
האוניברסיטה הפתוחהמועד ב · 2024 · סמסטר ב
★★★★★
Schemeתכנות פונקציונלימפרשיםפונקציות מסדר גבוהdefine
שאלה זו עוסקת בשרטוט של שפת "יירשגורי" (שפת PROC) המתוארת בספר הלימוד בפרק 3, בעמודות 74–84. שפה זו מאפשרת הגדרת פרוצדורות לא רקורסיביות.

בשאלה זו נרצה להוסיף לשפת "יירשגורי" יכולת עבודה עם enum בדומה לקיים בשפות תכנות אחרות. לשם כך נרחיב את השפה עם enum כפי שקיים בדוגמה לקיים בשפת RUST (אין צורך בידע מוקדם בשפה זו).

הגדרת enum מורכבת מאוסף של שמות לבחירתו.

נוסיף לשפה: ביטוי המחזיר enum חדש, ביטוי המאפשר להחזיר אחד השמות של enum קיים, וביטוי המאפשר לבחון את ערכי ה-enum.

להלן הדקדוקים המגדירים את 3 היכולות החדשות הנדרשות, לאחריהם תיאור הסמנטי על כל אחד מהם וכן הדגמות שימוש:

Expression ::= enum { {Identifier}*(,) }
               enum-exp (ids)

Expression ::= < Expression . Identifier >
               enum-elmt-exp (exm id)

Expression ::= match [ Identifier :: Expression ]
               { ?Identifier => Expression ; }*
               match-exp (enmid exp1 enmids exps)


ביטוי `enum-exp`: ביטוי בעל רשימת שמות של פחות שם אחד (ולכן אם הרשימה ריקה יש להדפיס שגיאה מתאימה). השמות מייצגים את ערכי ה-enum. הביטוי בודק אם השמות ה-enum כבר רשומים, ואז יוצר enum חדש ומחזיר אותו.

ביטוי `enum-elmt-exp`: ביטוי המקבל exm ו-id. הוא מחשב את exm ובודק שהתוצאה היא enum. לאחר מכן בודק ש-id הוא אחד הערכים של ה-enum שב-exm. במקרה ש-exm אינו enum, יש להדפיס שגיאה מתאימה. גם אם id אינו חלק מה-enum של exm, יש להדפיס שגיאה מתאימה. אחרת יש להחזיר את ערך ה-id המיוצג.

ביטוי `match`: ה-enmid הוא שם של ה-enum שהוגדר בסביבה. ה-exp1 הוא ביטוי שיש לחשב שמחזיר ערך של ה-enum. ה-enmids הוא רשימה של כל הערכים של ה-enum הנתון — על הרשימה להכיל בדיוק את כל הערכים ללא ערכים שלא שייכים אליו. במקרים שאין התאמה מלאה יש להדפיס שגיאה מתאימה. ה-exps הם רשימת הביטויים, אחד לכל ערך, שיש לחשב ולהחזיר את ערכו של הביטוי המתאים ל-exp1.

להלן מספר דוגמאות להמחשת השימוש של הביטויים החדשים לעבודה עם enum:

דוגמה 1:



בדוגמה זו, מוגדר enum בשם Colors המייצג את הצבעים Red Green Blue. לאחר מכן c מקבל לערכו אחד ה-enum המייצג את Green. לאחר מכן מבוצע ביטוי match על c ומוחזר 100 למקרה ה-Green.

דוגמה 2:



דוגמה זו רומה לדוגמה הקודמת, ובה c מחזיר ערכו. ניתן לראות שהסוג המוחזר הוא identifier-val, שהוא סוג חדש בשפת 'יירשגורי'.

דוגמה 3:



דוגמה זו רומה לדוגמה הקודמת, וממחישה שימוש שגוי ב-match. ניתן לראות שביטוי ה-match חסרה בדיקה לערך Blue ועל כן, שגיאה מוחזרת.

דוגמה 4:



בדוגמה זו, יש שימוש שגוי בביטוי enum-elmt-exp, כי i אינו enum (הוא מייצג ערך אחר הקיים בסביבה ההתחלתית).

דוגמה 5:



בדוגמה זו, Yellow אינו ערך של Colors ועל כן שגיאה מוחזרת.

דוגמה 6:



בדוגמה זו, יש הגדרת enum ללא ערכים, ולכן שגיאה מוחזרת.

דוגמה 7:



בדוגמה זו, מוגדר enum המייצג מאכלים שונים, וכן פרוצדורה Calories המקבלת מאכל (מרשימות המאכלים של ה-enum Foods) ומחזירה את כמות הקלוריות שלו. לבסוף מופעלת הפרוצדורה Calories עם הפרמטר Humus (חומוס) וערכה של הפרוצדורה הוא 170.

יש לממש את הביטויים הנדרשים בתוך שפת "יירשגורי" (PROC) בהתאם לדקדוק שהוגדר בשאלה. הקפידו לשמור על הגדרות הדוגמאות המקוריות (פרט למקרים בהם הם גורמים לשינויים בתוך הגדרות המקוריות של המפרש בלבד). יש להדפיס שגיאה מתאימה בכל מקרה שגיאה.
העתק שאלה
שתף שאלה
סמן כחשוב
סמן כבוצע
האוניברסיטה הפתוחהמועד א · 2024 · סמסטר ב
★★★★★
מפרשיםSchemeמעקב אחר קודתכנות פונקציונלי
שאלה זו עוסקת בשפת IMPLICIT-REFS המתוארת בספר הלימוד בעמודים 113–120.

ברצוננו להרחיב את שפה זו בהגדרת מצביע רב-מימדי, וגישה באמצעות הגדרתם.

להלן הרקורסיה המגדירה את הביטויים החדשים שיש להוסיף לשפה:

ביטוי `multiptr-exp`:

Expression ::= {&}+ (Expression)
  multiptr-exp (ptrs data)


ביטוי `multistar-exp`:

Expression ::= {*}+ (Expression)
  multistar-exp (stars v)


ביטוי `assign-exp` המורחב:

Expression ::= option Identifier = Expression
  assign-exp (opt id newval)

Option ::= ε | @


הסבר על הביטויים ותפקידם:

לביטוי assign-exp המוחדש יש option של @ או שאינו מופיע (ריקה ε). כאשר ה-option הוא ריקה (ε), ביטוי זה assign-exp כותב ישירות לתא הזיכרון של identifier, כמו set רגיל. כאשר ה-option הוא @, ה-identifier חייב להיות שם של משתנה רב-מימדי, ובמקרה זה ביטוי assign-exp יעדכן את הנחון (הערך) שאליו מצביע identifier לפי ערכו של ביטוי newval.

ביטוי multiptr-exp מאפשר להגדיר מצביע רב-מימדי (מצביע למצביע) על ידי שימוש ב-&. הביטוי ptrs הוא רשימת סמני & המגדירים את עומק המצביע. הרכיב data הוא ביטוי המייצג את הערך הבסיסי שאליו מצביע המצביע.

ביטוי multistar-exp הוא ביטוי הפניה (dereference) על מצביע רב-מימדי. ניתן להשתמש בו רק על ביטוי מסוג multiptr-exp; כל ניסיון אחר יגרור שגיאה.

להלן מספר דוגמות שימוש:

דוגמה 1:



בדוגמה זו p הוא מצביע תלת-מימדי (הלומר, מצביע למצביע למצביע ל-6). המצביע q הוא מצביע חד-מימדי לעבר 6. ולכן num הוא 6 ולכן הביטוי הוא (num-val 4).

דוגמה 2:



בדוגמה זו q מצביע חד-מימדי לעבר 6. ה-let השלישי מנסה לבצע 4 רמות dereference על q אך q הוא רק מצביע חד-מימדי (לא קיימים 4 מצביעים עליו) ולכן אמורה להתקבל שגיאה מתאימה.

דוגמה 3:



בדוגמה זו p הוא מצביע דו-מימדי על החנות. בגוף ה-let מבצעים פניה עם כניסה אחת עליו מה שמחזיר 6, ולכן ערכו של כל הביטוי הוא (num-val 1).

דוגמה 4:



בדוגמה זו יש ניסיון להפעיל ביטוי star-exp על ביטוי מסוג zero?-exp שאינו מסוג מצביע רב-מימדי ולכן אמורה להתקבל שגיאה מוגדרת.

דוגמה 5:



בדוגמה זו p הוא מצביע תלת-מימדי לפרוצדורה. בגוף ה-let יש פניה אל הפרוצדורה והפעלתה על 9 ולכן התוצאה הינה (num-val 2).

דוגמה 6:



בדוגמה זו p הוא מצביע תלת-מימדי לפרוצדורה. בגוף ה-let התוצאה היא מצביע דו-מימדי לפרוצדורה, ולכן ה-expval אמורה להחזיר מצביע רב-מימדי.

דוגמה 7:



בדוגמה זו p הוא מצביע תלת-מימדי לפרוצדורה. בגוף ה-let, set @p = 9 מעדכן את הנחון שאליו מצביע p להיות 9 במקום הפרוצדורה, ולבסוף מבצעים dereference מלא על p ומחזירים 9-2 ולכן הוא (num-val 7).

דוגמה 8:



בדוגמה זו, p הוא מצביע 4-מימדי על 8, q הוא מצביע דו-מימדי המצביע על אותו שרשרת מצביעים כמו p. בגוף ה-begin, set @q = 20 משנה את הערך שאליו מצביע q (רמה אחת מתחתיו), כלומר מעדכן את תא הזיכרון הבסיסי ל-20. לכן כעת ****(p) עובר 4 רמות ומגיע לאותו תא בסיסי שכעת מכיל 20, ולכן הניב הוא (num-val 17).

דוגמה 9:



בדוגמה זו, p הוא מצביע 4-מימדי לאחסון 8, q הוא מצביע דו-מימדי המשתף שרשרת עם p. set @p = 20 מעדכן את הנחון שאליו מצביע p (רמה אחת מתחתיו) ל-20, כך שגם q (שמצביע לאותה רמה) רואה כעת את הערך 20 בסוף שרשרתו. לאחר מכן set p = 5 משווה את p עצמו ל-5 (מספר). כעת **(q) מבצע dereference דו-מימדי דרך q ומגיע ל-20; ו-p הוא 5. לכן הניב הוא -(20, 5) = (num-val 15).

עליך לממש את השינויים הדרושים בתוך שפת IMPLICIT-REFS (שפת ייחסמוריות) בתוך קבצי המפרש, הקפד להסביר בקצרה בקבצי המפרש, ולציין את השורות הדרושות והמתחנות.

הוראות לחלקים הנלמדים:
1. הקפד על כתב ברור, ועל קוד מובן ומסודר.

2. הקפד על פתיחות וסגירות במקומות המתאימות.

3. התוצר אמור לשמור על הגדרת השפה הנדרשת שיוגדר לזה במפרש בשאלה.

4. על מנת לפשט קוד ארוך, כדאי להיעזר בפונקציות עזר (מחוץ value-of).

5. בפרט, הקפד על הבחנה ושימוש מכון בין ביטוי (expression) לבין תוצאת חישוב ביטוי (expval) לבין identifier.

6. ניקוד יורד על אי הבחנה ומימוש מכון של הרקורסיה הנחונה בשאלה, כלומר יש להקפיד על הכון ב-terminals, non-terminals הפעולות של פסיקור ( )* או { }+.
העתק שאלה
שתף שאלה
סמן כחשוב
סמן כבוצע
האוניברסיטה הפתוחהמועד ג · 2024 · סמסטר ב
★★★★★
מפרשיםמצבמודל הסביבהמעקב אחר קוד
בספר הלימוד בעמודות 113–120 מתוארת שפת "יירשגורי" (שפת IMPLICIT-REFS).

בשאלה זו נרצה לממש ביטוי חדש המסייע לבצע לולאות מסוגים שונים. ללולאה יש מבנה עם אסטרטגיה יחידה. בכל איטרציה של הלולאה, יש להשתמש בגוף הלולאה. לאסטרטגיות הלולאה כוללות תנאים (guards), באמצעותם ניתן לשלוט על הפסקת הלולאה לפני הזמן.

לשם כך נרחיב את שפת "יירשגורי" עם ביטוי חדש בשם for/proc.

להלן הדקדוק המגדיר את הביטוי החדש ותיאור התנהגות הביטוי:

Expression ::= for/proc ( identifier ;
                          | { identifier }*(,) | ;
                          | { Expression }*(,) | )
               {< Guard>}*
               {
                 Expression
               }
               forproc-exp (Id Ids Bodies Guards Body)

Guard ::= skip : Expression
          skip-guard (exp)

Guard ::= break : Expression
          break-guard (exp)


הסבר על הדקדוק והתנהגות הביטוי:

לביטוי forproc הרכיבים הבאים:
  • `Id` — המשתנה החדש לכרוך בביצוע הלולאה, אינו מוכר כסיום הלולאה.
  • `Ids` ו-`Bodies` — רשימות של שמות פרמטרים וגופי ביטויים בהתאמה. בכל איטרציה, ה-id ילקח מרשימת ids ויהיה שם הפרמטר בגוף הפרוצדורה שנקבע לפי הביטוי המקביל ברשימת bodies.
  • `Guards` — רשימות של Guard מסוג שני: skip ו-break. כל Guard מבוטא בביטוי. אם Guard מסוג skip מתקיים (מחזיר אמת), הלולאה מדלגת על האיטרציה הנוכחית וממשיכת לאיטרציה הבאה. ב-Guard מסוג break, כאשר הביטוי מחזיר אמת, הלולאה מסתיימת לאלתר. בכל איטרציה נבדקים כל ה-Guards בסדרם.
  • `Body` — זהו גוף הלולאה שיש לבצע בכל איטרציה.


הלולאה מסתיימת כאשר Guard מסוג break מחזיר אמת, או כאשר נגמרים האיברים ברשימות ה-Ids וה-Bodies.

לביטוי forproc-exp אין ערך מוחזר, ולכן יש להחזיר ערך פיקטיבי של num-val 27.

יש לבדוק ולהדפיס שגיאה בכל מקרה של שימוש לא תקין. יש לממש שגיאות מתאימות.

דוגמה 1 — להמחשת השימוש בביטוי החדש:



בדוגמה זו, מוגדרים 3 משתנים w1,w2,w3 המאותחלים לערכים 100,300,500 בהתאמה. לאחר מכן, מבוצעת לולאה for/proc עם משתנה לולאה בשם p. בלולאה יש 4 פרוצדורות (בכל איטרציה נבחרת p עם גוף שונה):

  • באיטרציה הראשונה, p מייצג פרוצדורה בעלת פרמטר a וגוף -(a,1). לא אחד מה-Guards מתקיים, ולכן מבוצע גוף הלולאה. מכיוון שה-p מקבל 1 ומחשב -(1,1)=0, w1 משתנה להיות 7000.
  • באיטרציה השנייה, p מייצג פרוצדורה בעלת פרמטר b וגוף -(b,2). ה-Guard מסוג skip מתקיים (כי -(2,2)=0), ולכן הלולאה מדלגת לאיטרציה הבאה.
  • באיטרציה השלישית, p מייצג פרוצדורה עם פרמטר c וגוף -(c,3). אף אחד מה-Guards לא מתקיים, ולכן מבוצע גוף הלולאה. w2 משתנה להיות p (הפרוצדורה הנוכחית).
  • באיטרציה הרביעית, p מייצג פרוצדורה עם פרמטר d וגוף -(d,4). אף אחד מה-Guards לא מתקיים, ולכן מבוצע גוף הלולאה. w3 משתנה להיות (p w1) = (p 7000) = -(7000,4) = 6996.


בסוף הלולאה מבוצע (w2 w3): w2 הוא הפרוצדורה מאיטרציה 3 (פרמטר c, גוף -(c,3)), ומופעלת עם w3=6996, ומחזירה -(6996,3)=6993.

דוגמה 2 — דוגמה שונה מעמ' 9:



בדוגמה זו, הדוגמה רומה לדוגמה הקודמת אך עם Guards שונים. ה-Guard הראשון הוא break (ולא skip). לכן באיטרציה הראשונה (p עם גוף -(a,1)): Guard ראשון בודק zero?((p 2)) = zero?(-(2,1)) = zero?(1) = שקר — ממשיכים. Guard שני בודק zero?((p 12)) = zero?(-(12,1)) = zero?(11) = שקר — ממשיכים. Guard שלישי בודק zero?((p 200)) = zero?(-(200,1)) = שקר — ממשיכים. מבוצע גוף הלולאה: zero?((p 1)) = zero?(0) = אמת, לכן w1=7000. לאחר מכן ממשיכים לאיטרציה הבאה. לבסוף הלולאה מסתיימת ומחושב -(w1,w2) = -(7000,300) = 6700.

יש לממש את הביטויים החדשים בתוך שפת "יירשגורי" (IMPLICIT-REFS), הקפידו לשמור על הגדרות הדוגמאות המקוריות (פרט למקרים בהם הם גורמים לשינויים בתוך הגדרות המקוריות של המפרש בלבד).
העתק שאלה
שתף שאלה
סמן כחשוב
סמן כבוצע
האוניברסיטה הפתוחהמועד א · 2024 · סמסטר ב
★★★★★
מפרשיםSchemeמעקב אחר קודתכנות פונקציונלימצב
בשאלה זו נוסיף לשפת IMPLICIT-REFS מרכיב חדש בשם event (אירוע) בהשראת שפת VisualBasic (IMPLICIT-REFS).

למשתנה ניתן לשייך מאפיין ממין event. המאפיינים של ה-event הם קבוצת פרוצדורות ורשימת המשתנים הרשומים לאירוע. בכל פעם שמופעל האירוע הוא מפעיל כל אחת מהפרוצדורות הרשומות אליו.

התחביר החדש:

Expression ::= event.create()


עם בנאי: event-create-exp()

Expression ::= <Identifier> += [ Expression ]+ 


עם בנאי: event-add-exp(evt, procs)

התנהגות הביטויים החדשים:
  • ביטוי event-create-exp: יוצר אירוע (event) חדש ומחזיר אותו.
  • ביטוי event-add-exp: רושם פרוצדורות לאירוע שנמצא בזיהוי <Identifier>. מחזיר את ערך הארגומנט האחרון (המשתנה שרשמנו אליו). הדקדוק הנתון בשאלה — ניקוד יורד על אי ניתוח ומימוש נכון של הדקדוק, כלומר יש להפקיד על זיהוי וטיפול נכון ב- terminals, non-terminals ופעולות סגור ( ), { }*, { }+.


להפעלת האירוע משתמשים ב-call-exp הקיים: (OnClick 50) מפעיל את כל הפרוצדורות הרשומות ל-OnClick עם הארגומנט 50.

דוגמאות:

דוגמה 1:



הסבר: a מתחיל ב-1000. נרשמות 3 עותקי dec_x ל-OnClick. פעולת (dec_x 100) מורידה a ל-900. לאחר מכן (OnClick 50) מפעיל את dec_x שלוש פעמים עם 50, מוריד a ב-150, לכן a = 750... (ראה פרטים בדוגמה).

דוגמה 2:



דוגמה 3:



דוגמה 4:



דוגמה 5:



דוגמה 6:



דוגמה 7:



ממשו והטמיעו את השינויים הדרושים כפי שהוגדרו והודגמו בתוך שפת IMPLICIT-REFS.

בתשובתכם, הקפידו להסביר היכן בדיוק נדרשים שינויים ותוספות בקבצי המפרש, ומהם השינויים והתוספות.

הנחיות כלליות לפתרון זהות לשאלה 1.
העתק שאלה
שתף שאלה
סמן כחשוב
סמן כבוצע
האוניברסיטה הפתוחהמועד ב · 2024 · סמסטר ב
★★★★★
מפרשיםמצבתכנות מונחה עצמיםSchemeהעברת מסרים
שאלה זו עוסקת בשדרוג של שפת ה־PROC המתוארת בספר הלימוד בפרק 3 (עמודים 74–81).

מאפשרים להרחיב את שפה זו בביטוי חדש בשם forsum-exp המאפשר לגלגל לולאה על רשימת ערכים מספריים, תוך אפשרות לעצירת הלולאה או דילוג על איברים. מרשימת ה-exps מהווה משתנה הלולאה אמור לסקור. מרשימת ה-guards מורכבת מביטויים (guards) יכולים להיות skip או break. הביטוי מחזיר את הסכום של תוצאות הפעולה לכל איבר ברשימה שעליו פעלה הלולאה.

התחביר של הביטוי החדש הוא:

Expression ::= for/sum [ identifier ({Expression}*(,)) ]
                { <guard> }*
                Expression
               for/end


עם ייצוג AST:

forsum-exp (id exps guards body)


כאשר:

guard ::= skip : Expression
  skip-guard (boolexp)

guard ::= break : Expression
  break-guard (boolexp)


הפעולה הכללית של הביטוי החדש:

ביטוי forsum-exp מורכב מהמרכיבים הבאים:
  • משתנה הזמן החוזר עליו הלולאה — id
  • מרשימת ה-exps שמהווה את הרשימה שמשתנה הלולאה אמור לסקור
  • מרשימת ה-guards המורכבת מביטויים שיכולים להיות skip או break (יכולים לחזור על עצמם) — כל סוג guard מורכב מביטוי בוליאני
  • הביטוי body שהוא גוף הלולאה


הלולאה עוברת על האיברים של רשימת הלולאה לפי מיקום id, מתחילה מהאיבר הראשון, ולכל אחד מהם בודקת תחילה אם מתקיים אחד מה-guards (בודקים לפי סדר הגדרתם). במידה ונמצא guard אחד שמתקיים, לא יבוצע גוף הלולאה עבור אותו איבר. אם הביטוי שהתקיים guard הוא מסוג skip, יש להמשיך את הלולאה ולעבור לאיבר הבא; ואם ה-guard שהתקיים הוא מסוג break, יש להפסיק את הלולאה ולהחזיר את הסכום שהצטבר עד לשלב זה. במידה ולא מצאנו guard אחד שמתקיים, יחשב גוף הלולאה והתוצאה תתווסף לסכום הכולל.

דוגמה 1:

(run "for/sum [i (1,2,3,20,5,90)]
             <skip:   zero?(-(i,1))>
             <break:  zero? (-(i,5))>
             <skip:   zero? (-(i,3))>
             -(i,-5)
      for/end")
=> (num-val 32)


בדוגמה 1, מוגדרת לולאה עם משתנה i ורשימת ערכים. ללולאה זו 3 guards. לכל האיברים: אם האיבר הוא 1 יש לדלג עליו, אם האיבר הוא 5 יש להפסיק, ואם האיבר הוא 3 יש לדלג. לפיכך הלולאה תפעל רק על האיברים 2 ו-20 (הביניהם 3 ו-1 מדולגים), עליהם הלולאה תחשב את ערכן של גוף הלולאה שמחזיר תוספת 5. לכן הסכום הכולל שיצטבר יהיה 32 (= (20+5) + (2+5)) ולכן הניב הסופי הוא (num-val 32).

דוגמה 2:

(run "for/sum [i ()]
             <skip:   zero?(-(i,1))>
             <break:  zero? (-(i,5))>
             <skip:   zero? (-(i,3))>
             -(i,-5)
      for/end")
=> interp.scm:79:16: forsum-exp: The list for i is empty


בדוגמה 2, מוגדרת לולאה עם רשימה ריקה, זה אינו תקין (על פי הרקורסיה המוגדרת) ולכן הורפסה הודעת שגיאה מתאימה.

דוגמה 3:

(run "for/sum [i (1,2,3,20,5,90)]
             -(i,-5)
      for/end")
=> (num-val 151)


בדוגמה 3, מוגדרת לולאה שאינה כוללת guards (אפס guards, תקין תחבירית) ולכן הלולאה תפעל על כל האיברים והתוצאה תהיה סכום כל האיברים בתוספת 5 לכל אחד.

עליך לממש את השינויים הדרושים בתוך שפת ה-PROC (שפת ייחסמוריות) בתוך קבצי המפרש, הקפד להסביר בקצרה בקבצי המפרש, ולציין את השורות הדרושות והמתחנות.

הוראות לחלקים הנלמדים:
1. הקפד על כתב ברור, ועל קוד מובן ומסודר.

2. הקפד על פתיחות וסגירות במקומות המתאימות.

3. התוצר אמור לשמור על הגדרת השפה הנדרשת שיוגדר לזה במפרש בשאלה.

4. על מנת לפשט קוד ארוך, כדאי להיעזר בפונקציות עזר (מחוץ value-of).

5. בפרט, הקפד על הבחנה ושימוש מכון בין ביטוי (expression) לבין תוצאת חישוב ביטוי (expval) לבין identifier.

6. ניקוד יורד על אי הבחנה ומימוש מכון של הרקורסיה הנחונה בשאלה, כלומר יש להקפיד על הכון ב-terminals, non-terminals הפעולות של פסיקור ( )* או { }+.
העתק שאלה
שתף שאלה
סמן כחשוב
סמן כבוצע
האוניברסיטה הפתוחהמועד ג · 2024 · סמסטר ב
★★★★★
מפרשיםתכנות פונקציונליSchemeמעקב אחר קוד
שאלה זו עוסקת בשדרוג של שפת "ויהיי" (שפת LET) המתוארת בספר הלימוד בפרק 3 בעמודים 60-74.

בשאלה זו, נרצה להוסיף לשפת "ויהיי" ביטוי חדש מסוג לולאת do המוגדרת על פי הדקדוק הבא ובאופן המוסבר ומודגם לאחר מכן.

להלן הדקדוק של לולאת do:

Expression ::= do (
                { < Identifier  Expression  Expression > }+
                { [ Expression  Expression ] }+
               )


מבנה הנתונים המייצג את הביטוי:

do-exp (ids inits steps bools results)


הסבר לדקדוק:

ביטוי do-exp מגדיר כמות שרירותית (לפחות אחד) של משתנים מספריים (ids), למשתנים יש ערכים התחלתיים הנתונים ע"י הביטויים inits, ובכל מחזור לולאה גדלים הצעדים הנתונים ע"י ביטויים steps.

כמו כן, ללולאה כמות שרירותית (לפחות אחד) של ביטויים בוליאניים (bools), בכל מחזור לולאה נבדקים הביטויים הבוליאניים, והראשון מביניהם שערכו אמת, יגרום ללולאה להיעצר ולהחזיר את ערכו המתאים מתוך ביטוי results המתאים לביטוי הבוליאני שנמצא אמת.

אם בבדיקת הביטויים הבוליאניים אין ביטוי שערכו אמת, הלולאה תעבור למחזור הבא שלה, כאשר כל אחד מהמשתנים גדל על פי הצעד המתאים לו, ואז שוב נבדקים הביטויים הבוליאניים כמו קודם. הלולאה תתבצע שוב ושוב, עד אשר ימצא מחזור שבו אחד התנאים הבוליאניים היה אמת. (כמובן שיכולה להתרחש לולאה אינסופית אך זו אחריותו של המתכנת ולא של המפרש)

הבהרות:
  • אתחול של משתנה לולאה do יכול להכיר כבר את המשתנים שכבר אותחלו לפניו.
  • קידום משתני לולאה נעשה על פי ערכם של המשתנים במצב הנוכחי.


דוגמה 1:

> (run "do(
          <a 0 4>
          <b 7 -(a,2)>
          <c -(b,1)  -(a,b)>
          [zero? (b)     -(a,c)]
          [zero? (-(c,-2))  -(a,5)]
        )
")
(num-val 3)
>


בדוגמה זו, התוכנית מורכבת מלולאת do המגדירה 3 משתנים a,b,c. בתחילה a שווה לאפס, b שווה ל-7, c שווה ל-1 (6- פחות 1).

כעת נבדקים התנאים הבוליאניים לפי סדר הופעתם. התנאי הבוליאני הראשון בודק האם ערכו של b הוא 0, תנאי זה אינו מתקיים כרגע. התנאי הבוליאני השני בודק האם ערכו של c הוא 2-, גם הוא לא מתקיים כרגע.

מאחר ואף תנאי בוליאני לא התקיים, הלולאה ממשיכה למחזור הבא שלה, שבו היא תעבוד עם משתנים a,b,c שערכם הוא כעת:
  • a שווה ל-4, כי היה לו 0 והתווסף לו 4
  • b שווה ל-5, כי היה לו 7 והוא גדל ב-2 (a-2), a במצבו הנוכחי (לפני שקודם) היה 0 ולכן a-2 זה 2-
  • ולכן b קטן ב-2 מ-7 לכן 5-
  • c שווה ל-1, כי היה לו 6 והתווסף לו a-b (לפני שקודמו) היה 0 ו-7- בהתאמה ולכן c קטן ב-7 ונהיה 1-


כעת נבדקים שוב התנאים הבוליאניים, וניתן לראות ששוב אף אחד מהם אינו נכון, ולכן הלולאה ממשיכה למחזור הבא שלה, עם משתנים a,b,c שערכם הוא:
  • a שווה ל-8, כי היה לו 4 והתווסף לו 4
  • b שווה ל-7, כי היה לו 5, והוא גדל ב-2 (a-2) שזה 2
  • c שווה ל-2, כי היה לו 1- והוא גדל ב-(a-b) שזה 1-


וכעת שוב נבדקים התנאים הבוליאניים (לפי הסדר בו הם כתובים) וכעת התנאי הבוליאני השני מתקיים! ולכן הלולאה נעצרת ומוחזר ערכו של הביטוי הכתוב לצד התנאי הבוליאני שהיה אמת, שבמקרה זה הביטוי הוא a-5 שערכו הנוכחי הוא 8-5=3 ולכן תוצאת התוכנית היא 3.

דוגמה 2:

> (run "do(
          [zero? (b)     -(a,c)]
          [zero? (-(c,-2))  -(a,5)]
        )
")
 interp.scm:72:15: do-exp: do loop with no variables are not allowed
>


בדוגמה זו יש לולאת do ללא הגדרת משתנים, על פי הדקדוק הנתון בשאלה נדרש לפחות משתנה אחד ולכן התקבלה הודעת שגיאה מתאימה.

דוגמה 3:

> (run "do(
          <a 0 4>
          <b 7 -(a,2)>
          <c -(b,1)  -(a,b)>
        )
")
 interp.scm:74:19: do-exp: do loop with no booleans are not allowed
>


בדוגמה זו יש לולאת do ללא הגדרת תנאים בוליאניים, על פי הדקדוק הנתון בשאלה נדרש לפחות תנאי בוליאני אחד ולכן התקבלה הודעת שגיאה מתאימה.

ממשו והטמיעו את השינויים הדרושים כפי שהוגדרו והודגמו לעיל בתוך שפת "ויהיי" (שפת LET). בתשובתכם, הקפידו להסביר היכן בדיוק נדרשים שינויים ותוספות בקבצי המפרש, ומהם השינויים והתוספות.

הנחיות כלליות לפתרון:
1. הקפידו על כתב ברור, ועל קוד מבני ומסודר.

2. הקפידו על פתיחת וסגירת סוגריים במקומות הנכונים.

3. הפתרון אמור לשמור על הגדרות השפה המקוריות (פרט לשינויי כזה נדרש שינויי כזה במפרש בשאלה).

4. על מנת לפשט קוד ארוך, כדאי ורצוי להיעזר בכתיבת פרוצדורות עזר (מחוץ ל-value-of או כאלה המוטמעות בתוכו).

5. בפתרונכם, הקפידו על אבחנה וכן שימוש נכון בין ביטוי (expression) לבין תוצאת חישוב ביטוי (expval) לבין identifier.

6. ניקוד יורד על אי ניתוח ומימוש נכון של הדקדוק הנתון בשאלה, כלומר יש להפקיד על זיהוי וטיפול נכון ב-terminals, non-terminals ופעולות של סגור ()* או { }+).
העתק שאלה
שתף שאלה
סמן כחשוב
סמן כבוצע
האוניברסיטה הפתוחהמועד ב · 2023 · סמסטר ב
★★★★★
מפרשיםSchemedefineתכנות פונקציונלירקורסיה

שאלות שפות תכנות באוניברסיטה הפתוחה עם פתרונות

מאגר מבחנים בשפות תכנות מהאוניברסיטה הפתוחה (אופ) - 24 שאלות ממוינות לפי נושא ורמת קושי, עם פתרונות מלאים לבדיקה עצמית. השאלות מכסות מועדים לאורך השנים, כולל מבחנים מ-2023, 2024, 2025 ו-2026. נושאים מרכזיים: תכנות פונקציונלי, Scheme, מודל הסביבה, מודל ההצבה, תכנות מונחה עצמים. ניתן לסנן שאלות חוזרות, להתאמן על נושא ספציפי או להריץ סימולציית מבחן לפני הבחינה. הכנה לשפות תכנות מתמקדת במודל הסביבה, תכנות פונקציונלי וזרמים — הנושאים הנפוצים ביותר במבחנים. לימוד עצמי עם שאלות ממבחני עבר, ממוינות לפי נושא, הוא הדרך הכי יעילה לזהות פערים לפני הבחינה.

prepd›שפות תכנות›אופ