סגור (שפות תכנות)

במדעי המחשב, סְגוֹראנגלית: Closure) היא פונקציה יחד עם סביבת ייחוס עבור המשתנים שאינם מקומיים בפונקציה. המינוח סְגוֹר משמש גם להגדיר תכונה של שפה, המאפשרת קיום של פונקציות סְגוֹר (או מחלקות).

סְגוֹר מאפשר לפונקציה לגשת למשתנים שהם מחוץ לטווח-ההכרה הלקסיקלי המיידי שלה. כלומר, משתנים שאינם מוגדרים בפונקציה הנוכחית, וגם אינם משתנים גלובליים. משתנים כאלה שנכרכו על ידי הסגור נקראים "upvalues". סביבת הייחוס כורכת שמות שאינם לוקליים אל המשתנים המתאימים בטווח ההכרה בזמן שבו נוצרה הפונקציה, ובכך מאריכה את משך החיים שלהם להיות לפחות כמשך החיים של פונקציית-הסְגוֹר עצמה. כאשר בקרת הזרימה נכנסת לפונקציה בשלב מאוחר יותר – כלומר, כאשר הפונקציה נקראת בפועל – ההתייחסות לשמות הללו היא התייחסות למשתנים הלא-מקומיים המקוריים שנלכדו על ידי הסְגוֹר.

רעיון הסגור פותח בשנות ה-60, ומומש במלואו לראשונה בשנת 1975, כתכונה של שפת תכנות בשפה Scheme במטרה לתמוך בפונקציות ממדרגה ראשונה בעלות טווח הכרה לקסיקלי. מאז עוצבו שפות רבות כך שיתמכו בסְגוֹר. שימוש מפורש בפונקציות-סְגוֹר נקשר לרוב עם תכנות פונקציונלי ושפות תכנות כדוגמת ML או LISP. שפות תכנות אימפרטיביות מסורתיות (כגון ALGOL, פסקל או C) אינן תומכות במימוש סְגוֹר כיוון שאין בהן תמיכה בשמות שאינם מקומיים (שקיימים רק בפונקציות מקוננות או אנונימיות – מבנים שלרוב אף אינם קיימים בשפות אלה) או בפונקציות מסדר גבוה – העברת פונקציה כפרמטר לפונקציה אחרת, או החזרת פונקציה כפרמטר מפונקציה אחרת (בניגוד להעברת מצביעים לפונקציה). שפות תכנות אימפרטיביות מודרניות, הכוללות מנגנון איסוף זבל (כגון Smalltalk, שפת התכנות מונחת העצמים הראשונה, #C, ובאופן מוגבל גם Java) ושפות מפורשות או שפות סקריפטים רבות כן כוללות תמיכה בפונקציות מסדר גבוה, ולכן גם בסְגוֹר.

עצמים (אובייקטים) בתכנות מונחה-עצמים הם מבחינה מסוימת סְגוֹר, כאשר ההתייחסות אל האובייקט עצמו (לרוב, באמצעות המילים השמורות: "this", "self" או "current") הכולל את אוסף הפונקציות השייכות לאובייקט, היא הכריכה הלא-לוקלית של הסְגוֹר.

קטע הקוד הבא בשפת פייתון 3 מגדיר פונקציה counter עם משתנה מקומי x ופונקציה מקוננת increment, בעלת גישה ל-x, כאשר מבחינתה הוא משתנה גלובלי. הפונקציה counter מחזירה את הפונקציה increment עם התייחסות למשתנה הלא-לוקלי x.

def counter():
    x = 0
    def increment(y):
        nonlocal x
        x += y
        print(x)
    return increment

counter1_increment = counter()
counter2_increment = counter()

counter1_increment(1) # prints 1
counter1_increment(7) # prints 8
counter2_increment(1) # prints 1
counter1_increment(1) # prints 9