תכנות פונקציונלי, מודל הסביבה, זרמים, תכנות לוגי ומערכות טיפוסים
(num-val 12)(num-val 9)(num-val 11)(num-val 2)(num-val 4)(proc-val ...)proc-val(num-val 6)(num-val 5)(bool-val #t)(bool-val #f)(num-val 12)(num-val 18)(num-val 6)(num-val 9)Expression ::= overload proc [ [identifier]* -> Expression ; ]+
overload-proc-exp(ids, bodies)Expression ::= (Expression | Expression }+)
call-exp(rator, rands)overload proc מגדיר פרוצדורה בשם p שלה מספר גרסאות. כל גרסה כוללת כמות פרמטרים שונה וגוף פרוצדורה שונה לביצוע. הגרסה הראשונה כוללת 2 פרמטרים, הגרסה השנייה היא כפרוצדורה ללא פרמטרים, והגרסה השלישית היא של פרוצדורה בעלת פרמטר יחיד. בגוף פעולת ה-let מופעלת הפרוצדורה p עם 2 פרמטרים, וזה מתאים לגרסה הראשונה שלה, ולכן מבוצעת פעולת החיסור בין הפרמטרים.( ), { }*, { }+.enum בדומה לקיים בשפות תכנות אחרות. לשם כך נרחיב את השפה עם enum כפי שקיים בדוגמה לקיים בשפת RUST (אין צורך בידע מוקדם בשפה זו).enum מורכבת מאוסף של שמות לבחירתו.enum חדש, ביטוי המאפשר להחזיר אחד השמות של enum קיים, וביטוי המאפשר לבחון את ערכי ה-enum.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. הביטוי בודק אם השמות ה-enum כבר רשומים, ואז יוצר enum חדש ומחזיר אותו.exm ו-id. הוא מחשב את exm ובודק שהתוצאה היא enum. לאחר מכן בודק ש-id הוא אחד הערכים של ה-enum שב-exm. במקרה ש-exm אינו enum, יש להדפיס שגיאה מתאימה. גם אם id אינו חלק מה-enum של exm, יש להדפיס שגיאה מתאימה. אחרת יש להחזיר את ערך ה-id המיוצג.enmid הוא שם של ה-enum שהוגדר בסביבה. ה-exp1 הוא ביטוי שיש לחשב שמחזיר ערך של ה-enum. ה-enmids הוא רשימה של כל הערכים של ה-enum הנתון — על הרשימה להכיל בדיוק את כל הערכים ללא ערכים שלא שייכים אליו. במקרים שאין התאמה מלאה יש להדפיס שגיאה מתאימה. ה-exps הם רשימת הביטויים, אחד לכל ערך, שיש לחשב ולהחזיר את ערכו של הביטוי המתאים ל-exp1.enum:enum בשם Colors המייצג את הצבעים Red Green Blue. לאחר מכן c מקבל לערכו אחד ה-enum המייצג את Green. לאחר מכן מבוצע ביטוי match על c ומוחזר 100 למקרה ה-Green.c מחזיר ערכו. ניתן לראות שהסוג המוחזר הוא identifier-val, שהוא סוג חדש בשפת 'יירשגורי'.match. ניתן לראות שביטוי ה-match חסרה בדיקה לערך Blue ועל כן, שגיאה מוחזרת.enum-elmt-exp, כי i אינו enum (הוא מייצג ערך אחר הקיים בסביבה ההתחלתית).Yellow אינו ערך של Colors ועל כן שגיאה מוחזרת.enum ללא ערכים, ולכן שגיאה מוחזרת.enum המייצג מאכלים שונים, וכן פרוצדורה Calories המקבלת מאכל (מרשימות המאכלים של ה-enum Foods) ומחזירה את כמות הקלוריות שלו. לבסוף מופעלת הפרוצדורה Calories עם הפרמטר Humus (חומוס) וערכה של הפרוצדורה הוא 170.Expression ::= {&}+ (Expression)
multiptr-exp (ptrs data)
Expression ::= {*}+ (Expression)
multistar-exp (stars v)
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; כל ניסיון אחר יגרור שגיאה.set @p = 9 מעדכן את הנחון שאליו מצביע p להיות 9 במקום הפרוצדורה, ולבסוף מבצעים dereference מלא על p ומחזירים 9-2 ולכן הוא (num-val 7).set @q = 20 משנה את הערך שאליו מצביע q (רמה אחת מתחתיו), כלומר מעדכן את תא הזיכרון הבסיסי ל-20. לכן כעת ****(p) עובר 4 רמות ומגיע לאותו תא בסיסי שכעת מכיל 20, ולכן הניב הוא (num-val 17).set @p = 20 מעדכן את הנחון שאליו מצביע p (רמה אחת מתחתיו) ל-20, כך שגם q (שמצביע לאותה רמה) רואה כעת את הערך 20 בסוף שרשרתו. לאחר מכן set p = 5 משווה את p עצמו ל-5 (מספר). כעת **(q) מבצע dereference דו-מימדי דרך q ומגיע ל-20; ו-p הוא 5. לכן הניב הוא -(20, 5) = (num-val 15).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.Guard מסוג שני: skip ו-break. כל Guard מבוטא בביטוי. אם Guard מסוג skip מתקיים (מחזיר אמת), הלולאה מדלגת על האיטרציה הנוכחית וממשיכת לאיטרציה הבאה. ב-Guard מסוג break, כאשר הביטוי מחזיר אמת, הלולאה מסתיימת לאלתר. בכל איטרציה נבדקים כל ה-Guards בסדרם.break מחזיר אמת, או כאשר נגמרים האיברים ברשימות ה-Ids וה-Bodies.forproc-exp אין ערך מוחזר, ולכן יש להחזיר ערך פיקטיבי של num-val 27.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.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.Expression ::= event.create()
event-create-exp()Expression ::= <Identifier> += [ Expression ]+
event-add-exp(evt, procs)<Identifier>. מחזיר את ערך הארגומנט האחרון (המשתנה שרשמנו אליו). הדקדוק הנתון בשאלה — ניקוד יורד על אי ניתוח ומימוש נכון של הדקדוק, כלומר יש להפקיד על זיהוי וטיפול נכון ב- terminals, non-terminals ופעולות סגור ( ), { }*, { }+.(OnClick 50) מפעיל את כל הפרוצדורות הרשומות ל-OnClick עם הארגומנט 50.(dec_x 100) מורידה a ל-900. לאחר מכן (OnClick 50) מפעיל את dec_x שלוש פעמים עם 50, מוריד a ב-150, לכן a = 750... (ראה פרטים בדוגמה).forsum-exp המאפשר לגלגל לולאה על רשימת ערכים מספריים, תוך אפשרות לעצירת הלולאה או דילוג על איברים. מרשימת ה-exps מהווה משתנה הלולאה אמור לסקור. מרשימת ה-guards מורכבת מביטויים (guards) יכולים להיות skip או break. הביטוי מחזיר את הסכום של תוצאות הפעולה לכל איבר ברשימה שעליו פעלה הלולאה.Expression ::= for/sum [ identifier ({Expression}*(,)) ]
{ <guard> }*
Expression
for/end
forsum-exp (id exps guards body)
guard ::= skip : Expression skip-guard (boolexp) guard ::= break : Expression break-guard (boolexp)
forsum-exp מורכב מהמרכיבים הבאים:id(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)
(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
(run "for/sum [i (1,2,3,20,5,90)]
-(i,-5)
for/end")
=> (num-val 151)
do המוגדרת על פי הדקדוק הבא ובאופן המוסבר ומודגם לאחר מכן.do:Expression ::= do (
{ < Identifier Expression Expression > }+
{ [ Expression Expression ] }+
)
do-exp (ids inits steps bools results)
do-exp מגדיר כמות שרירותית (לפחות אחד) של משתנים מספריים (ids), למשתנים יש ערכים התחלתיים הנתונים ע"י הביטויים inits, ובכל מחזור לולאה גדלים הצעדים הנתונים ע"י ביטויים steps.bools), בכל מחזור לולאה נבדקים הביטויים הבוליאניים, והראשון מביניהם שערכו אמת, יגרום ללולאה להיעצר ולהחזיר את ערכו המתאים מתוך ביטוי results המתאים לביטוי הבוליאני שנמצא אמת.do יכול להכיר כבר את המשתנים שכבר אותחלו לפניו.> (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 והתווסף לו 4b שווה ל-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 והתווסף לו 4b שווה ל-7, כי היה לו 5, והוא גדל ב-2 (a-2) שזה 2c שווה ל-2, כי היה לו 1- והוא גדל ב-(a-b) שזה 1-a-5 שערכו הנוכחי הוא 8-5=3 ולכן תוצאת התוכנית היא 3.> (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 ללא הגדרת משתנים, על פי הדקדוק הנתון בשאלה נדרש לפחות משתנה אחד ולכן התקבלה הודעת שגיאה מתאימה.> (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 ללא הגדרת תנאים בוליאניים, על פי הדקדוק הנתון בשאלה נדרש לפחות תנאי בוליאני אחד ולכן התקבלה הודעת שגיאה מתאימה.value-of או כאלה המוטמעות בתוכו).expression) לבין תוצאת חישוב ביטוי (expval) לבין identifier.)* או { }+).שפות תכנות – תכנות פונקציונלי, מודל הסביבה, זרמים, תכנות לוגי ומערכות טיפוסים. נושאים מרכזיים: תכנות פונקציונלי, Scheme, מודל הסביבה, מודל ההצבה, תכנות מונחה עצמים. 24 שאלות ממבחנים עם פתרונות, ממוינות לפי נושא ורמת קושי. ניתן לתרגל לפי נושאים, לסנן שאלות חוזרות ולהריץ מבחני סימולציה לפני הבחינה. הכנה לשפות תכנות מתמקדת במודל הסביבה, תכנות פונקציונלי וזרמים — הנושאים הנפוצים ביותר במבחנים. לימוד עצמי עם שאלות ממבחני עבר, ממוינות לפי נושא, הוא הדרך הכי יעילה לזהות פערים לפני הבחינה. המאגר כולל שאלות מהאוניברסיטה הפתוחה.