Structural Vs. Nominal Typing

Similar documents
ASP.Net MVC + Entity Framework Code First.

מבוא לתכנות ב- JAVA תרגול 7

A R E Y O U R E A L L Y A W A K E?

טכנולוגיית WPF מספקת למפתחים מודל תכנות מאוחד לחוויית בניית יישומיי

Rules Game (through lesson 30) by Nancy Decker Preparation: 1. Each rule board is immediately followed by at least three cards containing examples of

מבוא לתכנות - פיתוח משחקים ב Action Script 3.0

A JEW WALKS INTO A BAR: JEWISH IDENTITY IN NOT SUCH JEWISH PLACES

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

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

המבנה הגאומטרי של מידה

THINKING ABOUT REST THE ORIGIN OF SHABBOS

Hebrew Ulpan HEB Young Judaea Year Course in Israel American Jewish University College Initiative

קשירות.s,t V שני צמתים,G=(V,E) קלט: גרף מכוון מ- s t ל- t ; אחרת.0 אם יש מסלול מכוון פלט: הערה: הגרף נתון בייצוג של רשימות סמיכות.

Patents Basics. Yehuda Binder. (For copies contact:

מכונת מצבים סופית תרגול מס' 4. Moshe Malka & Ben lee Volk

FILED: NEW YORK COUNTY CLERK 07/16/2014 INDEX NO /2014 NYSCEF DOC. NO. 102 RECEIVED NYSCEF: 07/16/2014 EXHIBIT 5

אוניברסיטת בן גוריון בנגב

נספח: כישורי חשיבה )לפרק ראשון ושני( אנגלית (MODULE D) ספרות או מילון אנגלי-עברי-עברי-אנגלי

ניפוי שגיאות )Debug( מאת ישראל אברמוביץ

בוחן בתכנות בשפת C בצלחה

נספח: כישורי חשיבה )לפרק ראשון ושני( אנגלית (MODULE F) ספרות מילון אנגלי-אנגלי-עברי או מילון אנגלי-עברי-עברי-אנגלי

נספח: כישורי חשיבה )לפרק ראשון ושני( אנגלית (MODULE D) ספרות מילון אנגלי-אנגלי-עברי או מילון אנגלי-עברי-עברי-אנגלי

Reflection Session: Sustainability and Me

קורס מטלב לפיסיקאים שיעור מס' 10: משתנים מורכבים

מספר השאלון: Thinking Skills נספח: כישורי חשיבה )לפרק ראשון ושני( א נ ג ל י ת (MODULE F) ספרות )מילון הראפס אנגלי-אנגלי-ערבי(

פולימורפיזם. blog.csit.org.il מדעי המחשב

Practical Session No. 13 Amortized Analysis, Union/Find

ל"תוכנה" שכותבים, כמו פונקציה זו, קוראים "קוד"

נספח: כישורי חשיבה )לפרק ראשון ושני( אנגלית (MODULE F) ספרות או: מילון אנגלי-ערבי / ערבי-אנגלי או: מילון אנגלי-אנגלי-ערבי

FILED: NEW YORK COUNTY CLERK 07/16/2014 INDEX NO /2014 NYSCEF DOC. NO. 134 RECEIVED NYSCEF: 07/16/2014 EXHIBIT 37

נספח: כישורי חשיבה )לפרק ראשון ושני( אנגלית (MODULE D) ספרות או מילון אנגלי-עברי-עברי-אנגלי

זה. Nir Adar

אנגלית שאלון ז' ג רסה א' הוראות לנבחן בהצלחה! )4( ההנחיות בשאלון זה מנוסחות בלשון זכר ומכוונות לנבחנות ולנבחנים כאחד. (MODULE G)

אנגלית ספרות בהצלחה! /המשך מעבר לדף/ נספח: כישורי חשיבה )לפרק ראשון ושני( או: מילון אנגלי-ערבי / ערבי-אנגלי או: מילון אנגלי-אנגלי-ערבי

תצוגת LCD חיבור התצוגה לבקר. (Liquid Crystal Display) המערכת.

דיאגרמה לתיאור Classes

ANNEXURE "E1-1" FORM OF IRREVOCABLE STANDBY LETTER OF CREDIT PERFORMANCE OF CONTRACT (WHERE PRICES ARE NOT LINKED TO AN ESCALATION FORMULA)

ãówh,é ËÓÉÔê ÌW W É Å t" Y w f É ËÓÉÑ É èw É f Ñ u ð NNM YóQ' ÌW W É Y ÉgO d óqk É w f ym Éd É u ð NNM ÌWNQMH uqo ð NNM ÌWNQMH

אנגלית (MODULE E) בהצלחה!

interface Student {tag: Student, name: string; age: number;} const makestudent = ( name: string, age: number ) : Student =>

תורשכ ירפס לכ ץבוק " ב י קלח יללכ רעש

מערכים Haim Michael. All Rights Reserved.

אוניברסיטת בן גוריון בנגב

Theories of Justice

מבוא למחשב בשפת פייתון

מספר ת"ז: יש לסמן את התשובה הטובה ביותר בתשובון. לא יינתן ניקוד על סימון תשובה בטופס הבחינה או במחברת הבחינה.

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

תכנית סטארט עמותת יכולות, בשיתוף משרד החינוך א נ ג ל י ת שאלון א' Corresponds with Module A (Without Access to Information from Spoken Texts) גרסה א'

בהצלחה! (MODULE C) Hoffman, Y. (2014). The Universal English-Hebrew, Hebrew-English Dictionary

תרגול 8. Hash Tables

הצעת תשובות לשאלות בחינת הבגרות אנגלית

אנגלית שאלון ז' (MODULE G) ג רסה א' הוראות לנבחן )מילון אנגלי-ערבי / ערבי-אנגלי )

תכנית סטארט עמותת יכולות, בשיתוף משרד החינוך א נ ג ל י ת שאלון ב' Corresponds with Module B גרסה ב' הוראות לנבחן

מבוא למחשב בשפת Matlab

תרגול מספר 9: בנאים, שיטות של אובייקטים והכמסה מבוא למדעי המחשב - סמסטר א' תשע"א,תרגול מס' 9. נושאי התרגול: this

יסודות מבני נתונים. תרגול :9 ערימה - Heap

T H E S U N F L O W E R L I M I T S T O F O R G I V E N E S S

סה"כ נקודות סה"כ 31 נקודות סה"כ 21 תוכן עניינים של פתרון המבחן. לולאת for )נתון אלגוריתם... מעקב, פלט

שאלון ו' הוראות לנבחן

הבסיס כתיבת התכנית הראשונה שימוש במשתנים. הטיפוס הבסיסי object. הטיפוס הבסיסי string משפטי בקרה. שימוש ב- Enumerations. שימוש ב- Namespaces

מספר השאלון: הצעת תשובות לשאלות בחינת הבגרות אנגלית (MODULE C) מילון אנגלי-אנגלי-עברי או מילון אנגלי-עברי-עברי-אנגלי قاموس إنجليزي - إنجليزي - عربي

שאלון ו' הוראות לנבחן

מבוא לתכנות - פיתוח משחקים ב Action Script 3.0

Name Page 1 of 6. דף ט: This week s bechina starts at the two dots in the middle of

ב. משרד החינוך בגרות לנבחנים אקסטרניים א נ ג ל י ת (MODULE B) הוראות מיוחדות: )2( בתום הבחינה החזר את השאלון למשגיח. בהצלחה!


שאלון ד' הוראות לנבחן

ב. משרד החינוך בגרות לנבחנים אקסטרניים א נ ג ל י ת (MODULE B) הוראות מיוחדות: )2( בתום הבחינה החזר את השאלון למשגיח. בהצלחה!

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

Redirection The Input Buffer

תוכן העניינים: פרק סדרות סיכום תכונות הסדרה החשבונית:... 2 תשובות סופיות:...8 סיכום תכונות הסדרה ההנדסית:...10

כנס את תבואתו - He harvested the produce of his grapevine

Advisor Copy. Welcome the NCSYers to your session. Feel free to try a quick icebreaker to learn their names.

פרצות אבטחה נפוצות בהעלאת קבצים בעזרת PHP

אוסף תרגילים למעבדה ביוניקס - 4

דגשים: הערות: John Bryce Linux Forum: (Linux) BIND Mini How-To (In Hebrew) על שרת Red Hat Enterprise Linux גרסא.5.

למבחן ביסודות מדעי המחשב דוגמא

המחלקה למדעי המחשב, אוניברסיטת בן גוריון מבני נתונים, סמסטר אביב 2102 עבודת בית מספר - 2 מעשית

מבוא לרשתות - תרגול מס' 11 Transparent Bridges

Computer Structure. Exercise #1 יש להגיש את התשובות הסופיות על גבי טופס זה.

כפתור רדיו בחירה בודדת מתוך רשימת אפשרויות

תכנות בטוח חלק ב ' מאת עידו קנר

חוק זכויות הסוכן חוק חוזה סוכנות )סוכן מסחרי וספק(

Relationships: Everything Else is Commentary

שבות תחום מצוות עשה שזמן גרמא סמיכה תקיעה, שברים, תרועה. The אי ור of performing any מלאכה on Rosh HaShanah שופר in preparation of the

(MODULE E) ב ה צ ל ח ה!

מטוסים נופלים, כורים מתפוצצים זיכרון אוטומטי מקטסטרופות לומדים בניינים קורסים,

DNS פרק 4 ג' ברק גונן מבוסס על ספר הלימוד "רשתות מחשבים" עומר רוזנבוים 1

ראש השנה דף. 1. A) Our משנה says,... שנראה בעליל בין שלא נראה בעליל.בין Based on this,פסוק what does the word עליל mean?

דיאלוג מומחז בין מרטין בובר וקרל רוג'רס

נילי חמני

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

פרק מיון וחיפוש - לשם מה? הגדרה

A-level MODERN HEBREW 7672

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

Depth-First Search DFS

Design Patterns מאיר סלע מהדורה ראשונה 2004 הדפסה 1 כל הזכויות שמורות

NATIONAL COUNCIL OF YOUNG ISRAEL. Shavuot Nation JEWISH EDITION. Compiled by Gabi Weinberg Teen Program Director

Yetzer Shalom: Inclinations of Peace

Transcription:

שפות תכנות 234319 פרופ' יוסי גיל הפקולטה למדעי המחשב, הטכניון מכון טכנולוגי לישראל קיץ 2013 הרצאה מס' 6: טיפוסיות שמית ומבנית רשמה: איריס קלקה kalka.iris@gmail.com בשלב זה בקורס אנו עוסקים בתורת הטיפוסים. עד כה דיברנו על הנושאים הבאים: מבוא: למה צריך טיפוסים? 1. מערכות טיפוסים: אטומיים לעומת מורכבים. בנאי טיפוסים. 2. ההקשר של מערכות הטיפוסים של שפות תכנות: טיפוסי המכונה, תורת הטיפוסים התיאורתית. 3. סיווג של מערכות טיפוסים: דיברנו על הקריטריונים השונים, והיום נמשיך בסיווג חשוב נוסף... 4. פולימורפיזם :(polymorphism) בו נעסוק בשבוע הבא. 5. תוכן הענינים Structural Vs. Nominal Typing הקשיים בשקילות שמית שקילות מבנית בשפות C ו ++C טיפוסיות מבנית של רשומות קשיים בטיפוסיות שמית של רשומות תכנית המנסה לקרוא את הפלט של תכנית אחרת התקשרות בין שני חלקי תכנית.1.2.3.4.5.6.7 עמ 1 מתוך 17

Structural Vs. Nominal Typing מתי שני טיפוסים נחשבים שווים? למשל נניח שמשתנה x הוא מן הטיפוס T ונתון ערך v מן הטיפוס S. אזי נרצה לבדוק האם ההצבה: T x := v ; חוקית? ברור לנו כי אם S=T התשובה חיובית. (בשיעור הבא נסתכל על מקרים בהם ההצבה חוקית גם כאשר הטיפוסים אינם שווים). באופן דומה, נניח שפונקציה מצפה לפרמטר מסוג T. האם תהיה עבירה על חוקים הטיפוסים כאשר מועבר לה ערך אשר טיפוסו S? ברור כי ההעברה מותרת אם השיוויון S=T מתקיים (אם כי כאמור יתכנו אפשרויות נוספות בהן העברת הערך כאמור תהיה חוקית). ישנן שתי גישות עיקריות לשאלה מתי שני טיפוסים נחשבים לשווים: א. טיפוסיות מבנית או :Structural Typing הטיפוסים S=T אם המבנה שלהם זהה. כלומר, אם התחלנו מהטיפוסים האטומיים ובנינו שני טיפוסים בדיוק באותו אופן. ב. טיפוסיות שמית או :Nominal Typing הטיפוסים T=S אם הם הוגדרו ב"אותו מקום" והם נושאים את "אותו השם". (המונחים "אותו מקום" ו"אותו השם" הם מעט מעורפלים כעת, וזה בסדר גמור. הם יתבררו בהמשך.) הקשיים בשקילות שמית בשפת פסקל נהוגה טיפוסיות שמית אדוקה. בפרט, נסתכל על שיגרה למיון המוגדרת כך: Procedure sort(var a: Array [1..26] of Real) Begin (* *) end (כמה תזכורות: אנו מסמנים מילים שמורות בboldface. 1. שפת פסקל אינה מבחינה בין אותיות גדולות לקטנות. 2. הטיפוסReal הוא טיפוס מוגדר מראש. 3. המילה השמורהVar מציינת שהשיגרה אינה פועלת על העתק של הפרמטר, כי אם על הפרמטר עצמו. לפיכך, שינויים שתעשה 4. הפרוצדורה בפרמטר שלה ישתקפו מיידית במשתנה שהועבר לה כפרמטר.) ברור שהשיגרהSort לא תוכל למיין מערך שלInteger. אם נחשוב על כך מעט, נבין גם שהשיגרה לא עמ 2 מתוך 17

תוכל למיין מערך בו יש יותר מ 26 איברים או פחות מכך. יתירה מכך, השיגרה לא תוכל למיין גם מערך של 26 איברים אם האינדקסים שלו שונים, והם משתרעים, למשל, על פני התחום 25..0. מובן מאליו שהשגרה לא תוכל לפעול אם טווח האינדקסים במערך הוא A... Z (כמה תזכורות ביחס לשפת פסקל: פסקל מבחינה בין טיפוסים אורדינליים ובין טיפוסים שאינם אורדינליים 1. הטיפוסים האטומיים Integer, Character וBoolean הם טיפוסים אורדינליים. 2. אם T הוא טיפוס אורדינלי, ו t 1 ו t 2 הם שני ערכים של T אזי גם : t1..t2 הוא טיפוס אורדינלי, אשר נוצר על ידי בנאי הטיפוסים 3. של תת תחום (sub range) המסומן בשתי נקודות רצופות (..) אם T 1 הוא טיפוס אורדינלי,ו T 2 הוא טיפוס כלשהו (שאינו טיפוס סוג ב') אזי גם array[t 1 ] of T 2 הוא גם טיפוס הנוצר 4. על ידי בנאי הטיפוסים של מערך. למרות שבפסקל יש טיפוסיות חזקה בדרך כלל, אין בדיקה של טיפוסיות עבור תת תחום.) 5. אבל, העובדה המפתיעה באמת היא העובדה שהשיגרה לא תוכל למיין שום מערך. בפרט, אם ננסה לכתוב: VAR b: Array [1..26] of Real Begin (* *) sort(b); (* compilation error here! *) (* *) end נקבל שגיאת קומפילציה. הסיבה לכך היא ששני המופעים של הטיפוסReal Array [26..1] of שונים זה מזה אין להם אותו שם (למעשה אין להם שם), והם בוודאי לא הוגדרו באותו מקום. עמ 3 מתוך 17

כדי לבצע את המיון עלינו לכן להגדיר טיפוס חדש, לתת לו שם, ולהשתמש בשם זה, הן בהגדרת השיגרה, והן בהגדרת המשתנה אשר יועבר לה כפרמטר. TYPE Numbers = Array [1..26] of Real; Procedure sort(var a: Numbers) Begin (* *) end VAR b: Numbers Begin (* *) sort(b); (* no compilation error here! *) (* *) end במבט ראשון, האדיקות הזו עשוייה להרגיז. אבל, כוונתו של מתכנן השפה היתה טובה וחשובה: אילוץ המתכנת לתכנן מראש את טיפוסי הנתונים שעליהם התכנית שלו תעבוד, ולמנוע את המצב שבו שני טיפוסים שנועדו למטרות שונות בתכלית, יתערבבו במקרה. עמ 4 מתוך 17

שקילות מבנית בשפות C ו ++C הבעיה שנותנת שפת C לבעיה שהוצגה בדוגמת שיגרת המיון לעיל היא עירוב של טיפוסיות שמית וטיפוסיות מבנית. עבור בנאים שלstruct וunion יש טיפוסיות שמית. עבור כל שאר הבנאים, נהוגה טיפוסיות מבנית. ב ++C המצב דומה, אלא שגם הבנאיclass יוצר טיפוסיות שמית. בפרט הבנאים הבאים יוצרים טיפוסיות מבנית:.1 * מצביע.2 & רפרנס 3. const בנאי ההופך את הארגומנט שלו לטיפוס שאינו ניתן לשינוי אחרי שאותחל. 4. volatile בנאי ההופך את הארגומנט שלו לטיפוס "נדיף", כלומר טיפוס שהמהדר אינו יכול להניח לגביו שמשתנים מסוגו משנים את ערכם רק באמצעות שינויים שהתכנית מבצעת. 5. (*) מצביע לפונקציה.6 [] מערך. בפרט, נסתכל על דוגמת הקוד ב ++C שמשתמשת בכל אחד מששת הבנאים המנויים מעלה: const volatile int & f(char *a, double b[]) { return * new int; const volatile int & (*g)(char *a, double b[]) = f; const volatile int & (*h)(char *a, double b[]) = g; (כדאי לקורא לבדוק שהשתמשנו בכל אחד מששת הבנאים בדיוק פעם אחת) בדוגמא זו יש שלושה שימושים בטיפוס: const volatile int & (*)(char *a, double b) זהו טיפוס הפונקציה המקבלת שנית ארגומנטים, הראשון מטיפוסint והשני מהטיפוסdouble, והמחזירה רפרנס לint שהוא גםconst וגםvolatile. בשימוש הראשון, אנו יוצרים ערך חדש מטיפוס זה ונותנים לערך זה את השםf. (נשים לב לכך שיצירת ערך מהטיפוס הזה היא הגדרת פונקציה). בשימוש השני, אנו מגדירים משתנהgשזהו טיפוסו, ומציבים לו את הערך הזה. בשימוש השלישי, אנו יוצרים משתנה שלישי, h, ומציבים את תכנו של המשתנהg אליו. בזכות הטיפוסיות המבנית, הטיפוסים של הערךf והמשתניםg ו h הם זהים, על אף שבנינו אותם מאבני הבנין היסודיות (הטיפוסים האטומיים int, char ו (double בכל פעם מחדש. הזהות בין הטיפוסים נובעת מכך שסדרת עמ 5 מתוך 17

הבניה היא זהה. בכל מקום בו יש טיפוסיות מבנית, לא ניתן וגם אין טעם לתת "שם" לטיפוס, באופן שבו פסקל נותנת שמות לטיפוסים ויוצרת באמצעותו טיפוס חדש. במובן מסויים, כל טיפוס מבני "קיים", בין אם ניתן לו שם, ובין אם לאו, בין אם יצרנו אותו ובין אם לאו. המילה השמורהtypedef ב C, בניגוד למה שמשתמע ממנה, אינה "מגדירה" טיפוס חדש. היא רק נותנת שם לטיפוס קיים. בפרט, השקילות של הטיפוסים ממשיכה להתקיים בין אם נשתמש בtypedef ובין אם לאו, כפי שמדגים השכתוב הבא של הדוגמא שלמעלה: typedef const volatile int & (*T)(char *a, double b[]); const volatile int & f(char *a, double b[]) { return * new int; T g = f; const volatile int & (*h)(char *a, double b[]) = g; בשכתוב הזה, הצבנו אתf לg ואתg לh, למרות שהטיפוס שלg נראה כאחר מהטיפוסים שלf וh. נשים לב לכך שב C, הטיפוס של מערך אינו כולל את גודל המערך. כך למשל, בדוגמא הבאה, נגדיר פונקציה המקבלת מערך שמספר איבריו רבבה, והיא מדפיסה את האיבר השישי שבו (המצוי כידוע לכל בר בי רב בשפת C במקום שהאינדקס שלו 5): int f(double p[10000]) { return printf("p[5]=%g\n",p[5]); אחרי ההגדרה הזו, ננסה להעביר לפונקציה הזו מערך בן שלושה איברים. המהדיר לא יתאונן על כך שטיפוס הפרמטר האקטואילי שונה מזה של הפרמטר הפורמלי. עמ 6 מתוך 17

static double a[] = {4, 5, 6; static double b[] = {7, 8, 9; int main() { return f(a); הידור התכנית הזו (המתקבלת מצירוף שני הקטעים מעלה) יסתיים כשורה ללא שגיאות טיפוס הנובעות מבדיקה סטטית של טיפוסים. הרצת התכנית תיצור את הפלט הבא: p[5]=8 מהפלט הזה אנו יכולים ללמוד שני דברים: א. עצם קיום הפלט מורה על כך ששפת C היא Weakly Typed במובן זה שבזמן ריצה אין בדיקה של חריגות מגבולות של מערך. ב. ערכו של הפלט מלמד שמתכנת נבון, המכיר את הדרך שבה שפת C מנהלת את הזכרון שלה, יכול במקרים רבים לחזות את תוצאותיהן של חריגות מגבולות מערך, ושל שגיאות טיפוס מסויימות. בשפת Java יש שני בנאי טיפוסים בלבד: מערך, ומחלקה.(class) באופן דומה לשפת C, בשפת Java מתקיימת טיפוסיות שמית לגבי מחלקות, וטיפוסיות מבנית לגבי מערכים, וגם בשפה זו גודל המערך אינו חלק מהטיפוס. אולם, בשונה משפת C, בשפת Java מבצעת בדיקה דינמית (בזמן ריצה) של חריגה מגדלי מערכים, ובהתאם לכך, ערך מטיפוס מערך בשפה זו, נושא עמו בזמן ריצה את גדלו. עמ 7 מתוך 17

טיפוסיות מבנית של רשומות תיתכן גם טיפוסיות מבנית לגבי רשומות. הנה דוגמא לשני טיפוסים רשומות שיהיו שקולים בשפה אשר בה יש טיפוסיות מבנית Record Person { Int id; Boolean gender; Record Human { Int id; Boolean gender; טיפוסיות מבנית בין רשימות אינה נפוצה כל כך, למרות שהיא קיימת בשפות כמו OCAML שהיא ואריאנט של.ML הסיבה היא שטיפוסיות מבנית יכולה ליצור בלבול בין טיפוסים שהם לכאורה דומים, אבל הם לא שונים בתכלית, כמו למשל בדוגמא הבאה: Record Customer { Int id; String name; Record Supplier { Int id; String name; שפה הבוחרת להפעיל טיפוסיות מבנית, יכולה לעיתים להתיר להפעיל חוקים אלגבריים של שיוויון. בטיפוסיות מבנית לעיתים קורה שישנו היתר להפעיל חוקים אלגבריים כדי לשנות את המבנה. כך למשל ב ML מתקיים השוויון: (int * int) > int = int > int > int (למעשה זהו שקר... זה רק נראה כך: ב ML כל הפונקציות מקבלות ארגומנט אחד ומחזירות ערך אחד. פונקציות שמקבלות כביכול שני ארגומנטים, מקבלות ארגומנט אחד, ומחזירות בתמורה פונקציה שמקבלת את הארגומנט עמ 8 מתוך 17

השני, ומחזירה את התוצאה הסופית). ניתן גם לדמיין טיפוסיות מבנית שמפעילה את החוק הקומוטטיבי, האסוציאטיבי, את חוק הפילוג ועוד. ניתן גם לתאר טיפוסיות מבנית משוכללת שמוחקת את התוויות בהגדרת רשומה, אבל אין ספק ששינויים כאלו עשויים לגרום לבלבול. אפשר להפליג עוד בטיפוסיות המבנית, ולהתיר שינויים של יותר כפי שמדגימה הדוגמה הבאה: תוויות.(lables) סכנת הטעית המתכנת גדולה אף Record Book { String author; Int edition; Record Street { String city; Int length; בכל זאת, נשים לב לכך שהשפות C ו ++C מתירות מחיקה של תוויות ושינוי שמן בהגדרת הפרמטרים לפונקציה. typedef const volatile int & (*T)(char [], double []); // Note that in the above typedef, the function s // arguments are anonymous. const volatile int & f(char *a, double b[]) { return * new int; T g = f; const volatile int & (*h)(char *c, double d[]) = g; // Note that in the above the function s // arguments take different names than in the function body. עוד כדאי לשים לב לכך שבשפות אלו, הטיפוסים של מצביע ושל מערך נחשבים כשקולים בקריאה לפונקציה. כך עמ 9 מתוך 17

למשל בדוגמא לעיל, טיפוס הארגומנט הראשון מתחלף בין מערך לבין מצביע. קשיים בטיפוסיות שמית של רשומות האם טיפוסיות שמית לרשומות נקיה מבעיות? מסתבר שלא. יש שני קשיים עיקריים: קלט/פלט וקשר עם העולם החיצון. חיבור בין חלקי תכנית הכתובים באותו מקום..1.2 עמ 10 מתוך 17

תכנית המנסה לקרוא את הפלט של תכנית אחרת ננסה למשל לכתוב תכנית פסקל P2 הקוראת את הפלט של תכנית אחרת P1. נניח למשל שהתכנית P1 אוספת בזמן אמת את נתוני המכירות של חברה כלשהי, ואילו התכנית P2 קוראת את הנתונים אשר נאספו קודם לכן על ידי התכנית P1. לשם כך, נרצה לכתוב את ההגדרות הבאות בתכנית P1: TYPE Sale = Record amount: Integer; quanitty: Integer; id: Integer; customer: Customer; (* *) end VAR log: File of Sale; אפילו אם נעתיק את ההגדרות הללו כלשונן לתכנית P2, הקריאה של הנתונים מהקובץ אשר הכינה התכנית P1 תהיה "לא חוקית". הסיבה לכך היא שההגדרה של הטיפוסSale היא אמנם זהה, ויש לה אותו שם, אבל היא לא התבצעה באותו מקום. דווקא במקרה זה, המניעות לקרוא את הנתונים בקובץ אינה שרירותית כלל וכלל. שהרי, ברור שאם יהיה שינוי קל בטיפוסSale (למשל כתוצאה משינוי הטיפוסCustomer ) באחת מבין שתי התכניות, הרי הנתונים שנשמרים בקובץ המשמש לתקשורת כבר לא יהיו זהים, ותחול שגיאת זמן ריצה. חשוב להבין כי הבעיה אינה רק בקבצים, אלא גם בתקשורת באינטרנט ובכל תקשורת אחרת בין תוכניות. נשים לב גם לכך שהבעיה תקרה גם אם התכניות P1 ו P2 הן זהות. תכנית המנסה לקרוא את הנתונים שהיא עצמה כתבה בהרצה קודמת שלה, גם כן תסבול מאותה בעיה. יתכן שבין שתי ההרצות, התכנית הודרה שוב, והיו שינויים קלים בהגדרה. בטיפוסיות שמית, כל הרצה של התכנית יוצרת טיפוס חדש. בפועל, ניתן לכתוב בפסקל תכניות שתחלפנה נתונים באמצעות קבצים. זו בדיוק אחת הנקודות שבהן יש חורים במערכת הטיפוסים. כדי לאכוף את הטיפוסיות השמית לגבי נתונים חיצוניים, היה צורך לקדד באופן כלשהו עם הנתונים גם את הטיפוס שלהם, וגם את ה"מקום" שבו הן הוגדרו. מקום זה צריך לכלול בתוכו גם את התכנית עמ 11 מתוך 17

כולה, וגם (במידה ורוצים להביא את האדיקות של הטיפוסיות השמית לקיצון( את הזמן שבה התכנית הודרה, שם המהדר, ואולי אף העת המדוייקת שבה היא הורצה. קידוד זה הוא קשה ומסובך, ואינו נעשה בפועל. בדרך כלל, אין בדיקה של ממש של הטיפוס של הנתונים בקבצים. ושגיאות הטיפוס, אם תיווצרנה, הן באחריותו של המתכנת. על כן, הדרך היחידה להעביר נתונים בין שתי תכניות פסקל באופן חוקי היא באמצעות יצירת קובץ טכסט, וקידוד הנתונים בתווים בתכנית המעבירה. על התכנית המקבלת במקרה זה לקרוא את הנתונים ולפענח אותם. כדי לעשות זאת יש לכתוב לקובץ שהטיפוס שלו הוא File of Character למעשה, בדיקה נוספת תגלה כי הגדרת הטיפוס הזו סובלת מבעיה דומה, שכן הטיפוס File of Character הוא טיפוס שונה בשתי התכניות. זו הסיבה שבפסקל ישנו טיפוס מוגדר מראש, text המציין טיפוס של קובץ של תווים, והטיפוס הזה מוכר בשתי התכניות. (למעשה הטיפוסCharacter File of והטיפוסtext הם מעט שונים, משום שהטיפוסtext מתאר קובץ המתחלק לשורות.) החיסרון בשיטה זו הוא המאמץ הרב בכתיבת שגרות הקידוד והפענוח, והנטל לשנותן בכל פעם שישנו שינוי בטיפוס. לעומת זאת, בשפות שבהן יש טיפוסיות מבנית, ההתאמה בין טיפוס הנתונים בשתי התכניות היא התאמה מבנית. במקרה זה, שמירת הנתונים תכיל גם את המבנה שלהם, ולא ניתן יהיה לפתוח את הקובץ אם הנתונים בו יהיו במבנה שונה מהמבנה לו מצפה התכנית הקוראת. הקושי הזה שבטיפוסיות שמית הוא בדיוק הסיבה שבשפות העוסקות בבסיסי נתונים, כגון SQL יש טיפוסיות מבנית. עמ 12 מתוך 17

התקשרות בין חלקי תכנית נניח שאנו עובדים בשפת תכנות X אשר בה נוהגת טיפוסיות שמית והינה בטוחה, ונניח שאפשר לכתוב בשפה זו תכניות המתפרסות על מספר קבצים. בדוגמא הבאה, יש לנו שני קבצים: a.x ו :b.x // File a.x: T u; f(u); // File b.x: f(t t){ בדוגמא זו, שני חלקי התכנית מתקשרים זה עם זה, כאשר החלק הראשון קורא לפונקציה המוגדרת בחלק השני. טיפוס הפרמטר לפונקציה הואT. על כן הטיפוסT חייב להיות מוכר בשני חלקי התכנית. היכן עלינו להגדיר את הטיפוס הזה? היכן נגדיר את הטיפוס? אם לא נגדיר אותו באף אחד מהקבצים הוא לא יוכר כלל. אם נגדיר אותו ב a.x הטיפוס לא יוכר ב.b.X אם נגדיר אותו ב b.x הטיפוס לא יוכר ב.a.X אם נגדיר אותו בשניהם, שתי ההגדרות תהיינה שונות בגלל הטיפוסיות השמית..1.2.3.4 נראה כי הפתרון היחיד שנותר הוא שהטיפוס T יהיה טיפוס המוגדר מראש בשפה, או טיפוס פרימיטיבי. כמובן שפתרון זה יגרום לתסכול רב למתכנתים. מסתבר שישנו פתרון מתחכם נוסף שבו טרם ההידור נחבר את שני הקבצים יחד. פתרון זה אינו מעשי, משום שחלוקה של תכנית לקבצים מיועדת בין היתר כדי לאפשר הידור נפרד. אשר על כן, יש קושי מובנה בשפת תכנות בעלת טיפוסיות שמית המאפשרת לכתוב תכניות המתפרסות על פני יותר מקובץ אחד. זו אחת הסיבות ששפת פסקל הוגדרה כאוטרקית: העובדה שכל התכנית כולה מצוייה בקובץ אחד, מאפשרת בדיקה קלה ופשוטה של הטיפוסיות השמית, ואינה מביאה לתהיות מעיקות בדבר הגדרה השקילות התלוייה בכך שההגדרת הטיפוס נעשתה ב"אותו המקום" ועם "אותו השם". הפתרון שמציעה שפת C שגם בה נוהגת טיפוסיות שמית של רשומות, הוא הגדרת הטיפוס בשני הקבצים. כדי להבטיח שההגדרה תהיה זהה, נהוג להשתמש לכלול קובץ inclusion) (file המכיל את הגדרת הטיפוס. אבל, זהו רק ענין מכני טכני. הקדם מעבד אינו מכיר כלל את שפת C ושפת C אינה מכירה את הקדם מעבד. למעשה, בשפת C אין חובה כלל להשתמש בקדם מעבד. הנה תכנית שמדגימה כיצד ניתן לחזור על הגדרת הטיפוס בשני קבצים שונים מבלי להכליל קובץ עזר: עמ 13 מתוך 17

// File: a.c struct R { int ans; x = {42; extern int f(struct R *); int main() { return f(&x); // File: b.c struct R {int ans;; int f(struct R *a) { printf( "ans=%d\n", a >ans ); return 0; כאשר נהדר את שני הקבצים הללו, נקשר אותם, ונריץ את הקובץ המקושר, הפלט יהיה: ans=42 נשים לב לכך שאמנם הטיפוסR struct מוגדר בשני הקבצים, אבל הוא בוודאי לא מוגדר באותו מקום, וישנם הבדלים קלים בריווח בין שתי ההגדרות הללו. במובן מסויים שפת C ויתרה על הטיפוסיות השמית (שכן הטיפוס הוגדר בשני מקומות שונים עם אותו השם). למעשה, שיוויון טיפוסים בין קבצים של שפת C מוגדר באופן מבני, ולא באופן שמי. למעשה הויתור הוא גדול יותר. החלוקה הזו לקבצים פועלת רק בזכות העובדה שבשפת C יש.weak typing אין בדיקה ממשית של טיפוס הארגומנט לפונקציה. נוכל על כן לכתוב גירסה נוספת של התכנית שמחולקת לשני חלקים שבה אין התאמות בין ההגדרות. // File: c.c struct S { int rep; char q; x = {42; extern int f(struct S *); int main() { return f(&x); //File: d.c struct R {float ans;; int f(struct R *a) { printf( "ans=%g\n", a >ans ); return 0; נשים לב לכך שהפונקציה אמנם מוגדרת באותו שם בשני הקבצים, אבל הטיפוס שלה שונה. באחד הקבצים היא עמ 14 מתוך 17

מקבלת ארגומנט מסוג מצביע לטיפוסS,struct ואילו בקובץ האחר, היא מקבלת ארגומנט מהטיפוס. struct R לא זו בלבד ששמות טיפוסי הארגומנטים הם שונים, גם המבנה שלהם שונה לגמרי. אחד הטיפוסים מכיל שני שדות, והאחר מכיל שדה אחד. גם טיפוסי השדות ושמותיהם בשני טיפוסי הרשומות הם שונים בתכלית. בכל זאת, ניתן להדר את הקבצים הללו, לקשר ביניהם, ולהריץ את התוצאה. שגיאת הטיפוס שתחול כאן בזמן ריצה לא תתגלה ותפלט יהיה ans=5.88545e 44 נשים לכ לכך ששימוש בקובץ מוכלל יכול להקטין את הסיכוי של שגיאות מסוג זה, אך הוא אינו יכול למנוע אותן לחלוטין. בפרט, מתכנת אשר חומד לו לצון (או, רחמנא לצלן, חורש זדון) יוכל להדר קובץ מקור אחד, לשנות את הקובץ המוכלל, ואז להדר את הקובץ האחר. עיון נוסף בדוגמא לעיל מביא למסקנה שבעיית השקילות של הטיפוסים היא בעיקרה שקילות הטיפוסים של שתי ההגדרות השונות של הטיפוס של הפונקציה f בשני הקבצים היוצרים את התכנית. הלינקר אינו בודק כי הטיפוס של הגדרת הפונקציה בקובץ אחד, הוא הטיפוס אשר אליו מתייחס הקובץ האחר. הנה דוגמא המוכיחה זאת: // File: e.c double f(double); int main() { printf( "Returned: %g\n", f(0) ); return 0; // File: f.c int f(int i) { printf( "Passed: %d\n", i ); return 3; טיפוס הפונקציהf בקובץ e.c הוא double (*)(double) int (*)(int) ואילו טיפוסה שלf בקובץ f.c הוא: למרות אי התאימות בין הטיפוסים, ההידור והקישור של שני הקבצים הללו יחדיו לא יניב שגיאות טיפוס. הפלט לעומת זאת יעיד על כך שהביצוע אכן הפר את חוקי הטיפוס, באשר התכנית מדפיסה ערך מטיפוסdouble עמ 15 מתוך 17

כאילו הואint ולהיפך. Passed: 1 Returned: 0 הדוגמא הבאה מוכיחה שאין בדיקה גם של טיפוסים של רשומות בין חלקי תכנית שונים בשפת C: // File: g.c // File: h.c static const char u[] = "42"; struct { // Anonymous type const char *x; long y; v = { "Question", (long) &u ; int main() { return f(); struct S { int a; const char *q; double misc; ; extern struct S v; int f() { printf( "Question=%s\n", v.q ); printf( "Answer=%d\n", v.a ); return 0; אף כאן, לא תופענה שגיאות טיפוס בהידור ובקישור של שני החלקים, למרות שהטיפוס של המשתנה v הוא אחר לחלוטין בשני הקבצים. בקובץ האחד הוא טיפוס אנונימי, ובאחר הוא טיפוס שניתן לו שם. אף מבנה הטיפוס הוא שונה לגמרי: מספר השדות, הטיפוס שלהם, והשמות שלהם הם אחרים. הפלט של התכנית המקושרת מדגים שוב הפרות של חוקי הטיפוסים בזמן ריצה: Question=42 Answer=4195879 עמ 16 מתוך 17

המסקנה היא ששיוויון טיפוס רשומות (טיפוסיות שמית) בין קבצים של שפת C אינו נבדק בזמן הידור. באופן דומה, שיוויון טיפוס פונקציות (טיפוסיות מבנים) בין קבצים אף היא אינה נבדקת. חוקי שיוויון הטיפוס לא נאכפים, ושגיאות טיפוס בין קבצים שונים יכולות לקרות. שגיאות כאלו יכולות לגרום לשגיאות זמן ריצה מוזרות, שתגרומנה לעצירת התכנית בזמן ביצוע, ללא דיווח על שגיאת טיפוס. גרוע מכך, כפי שהדוגמא מוכיחה, יתכן ששגיאות טיפוס שכאלו תבאנה לביצוע שגוי שיהיה קשה לעמוד על מקורו. הבעיה המהותית כאן היא העובדה שהלינקר אינו מכיר את הטיפוסים של השפה העילית. מתכנני שפת C התחכמו ללינקר באמצעות המוסכמה של קובץ מוכלל, אך למוסכמה זו יש כוח מוגבל. בפסקל לעומת זאת, ההגבלה של התכנית לקובץ אחד התגלתה כבלתי נסבלת על ידי מתכנתים שרצו להשתמש בה לתכניות גדולות. נוצרו לכן דיאלקטים של פסקל אשר בהם הטיפוסיות השמית נשמרת, ויש בדיקה של טיפוסים גם בין יחידות הידור נפרדות. הדרך לממש זאת היא מעט מורכבת. מודול a.pas שירצה להשתמש ב b.pas (בדיאלקטים של פסקל רווח השם Unit כדי לציין קובץ) יכיל את הפקודה: uses b; ההידור של b.pas אינו יוצר קובץ object רגיל, אלא קובץ object מורחכ. בקובץ המורחב הזה, שומר המהדר את מבני הנתונים הפנימיים שלו, המתארים את ההגדרות של הטיפוסים אשר הוגדרו ב.b.pas ההוראה uses b; גורמת למהדר לטעון את מבני הנתונים השמורים מקובץ ה object המורחב המתאים אל תוך.a.pas טעינה זו משחזרת על כן את ההגדררות הטיפוסים השמיות כפי שהיו בזמן ש b.pas הודר, וכך מתאפשרת הטיפוסיות השמית בין יחידות הידור שונות. השיטה הזו יוצרת קושי כאשר יש תלות מעגלית בין יחידות. יש פתרון חלקי לתלות מעגלית כזו בדיאלקטים הנפוצים של פסקל. בשפת אייפל נדרשים לעיתים ארבע איטרציות של הידור כדי להסדיר תלויות מעגליות. נשים לב לכך שאף שיטה זו אינה חסינה מפני זדון. מתכנת מרושע יכול ולכן גם עלול לשנות את קובץ ה object המורחב. שפת Java משתמשת גם היא בשיטה דומה של קובץ object מורחב. גדולתה של השפה הוא בכך שאף פעולות זדוניות מסוג זה, לא תוכלנה לגרום לתכנית לבצע דברים אשר נאסרו עליה, כמו למשל גישה לכתובת לא חוקית. עמ 17 מתוך 17