תכנות פונקציונלי, מודל הסביבה, זרמים, תכנות לוגי ומערכות טיפוסים
(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.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.)* או { }+).Expression ::= try { Expression }
{ catch [ Except ] : Expression ; }*
{ finally : Expression ; }*
try-exp (exp1 excpts excptexps finexps)Expression ::= throw Except
throw-exp (excpt)Except ::= message Exception (msg) message ::= general | not a number | not a boolean | environment
exp1 הוא הביטוי בבלוק ה-try.excpts הוא רשימת החריגות שב-catch; החריגה הראשונה ברשימה המתאימה לחריגה שנזרקה תטופל.excptexps הוא רשימת הביטויים המתאימים לחריגות ב-catch.finexps הוא הביטוי ב-finally (רשימה ריקה או אחת); מבוצע תמיד בסוף.value-of או כאלה המוטמעות בתוכו).שאלות תרגול בשפות תכנות בנושא Scheme ממבחנים של האוניברסיטה הפתוחה. השאלות ממוינות לפי רמת קושי, עם פתרונות לבדיקה עצמית - כך שניתן ללמוד מטעויות ולהבין את דרך הפתרון לפני הבחינה. ניתן לאתר שאלות חוזרות ולהריץ מבחני סימולציה ממוקדים בנושא Scheme.