ביטויי למבדה ב- C ++

Lambda Expressions C



למה ביטוי למבדה?

שקול את המשפט הבא:

intmyInt= 52;

כאן, myInt הוא מזהה, ערך l. 52 הוא ערך פשוטו כמשמעו. כיום אפשר לקודד פונקציה במיוחד ולהעמיד אותה במיקום של 52. פונקציה כזו נקראת ביטוי למבדה. שקול גם את התוכנית הקצרה הבאה:







#לִכלוֹל

באמצעות מרחב שמותשעה (ות;

intfn(intדרך)

{

intתשובה=דרך+ 3;

לַחֲזוֹרתשובה;

}


intרָאשִׁי()

{

fn(5);



לַחֲזוֹר 0;

}

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



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



תוכן המאמר

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

בתוכנית הבאה, פונקציה, שהיא ביטוי למבדה, מוקצה למשתנה:





#לִכלוֹל

באמצעות מרחב שמותשעה (ות;

אוטומטיfn= [](intתפסיק)

{

intתשובה=תפסיק+ 3;

לַחֲזוֹרתשובה;

};


intרָאשִׁי()

{

אוטומטיvariab=fn(2);

עֲלוּת <<variab<< ' n';


לַחֲזוֹר 0;

}

הפלט הוא:

5

מחוץ לפונקציה הראשית (), קיים המשתנה, fn. הסוג שלו הוא אוטומטי. אוטומטי במצב זה פירושו שהסוג בפועל, כגון int או float, נקבע על ידי האופרנד הנכון של מפעיל ההקצאה (=). מימין לאופרטור ההקצאה מופיע ביטוי למבדה. ביטוי למבדה הוא פונקציה ללא סוג ההחזרה הקודם. שימו לב לשימוש ומיקום הסוגריים המרובעים, []. הפונקציה מחזירה 5, int, שתקבע את הסוג של fn.



בפונקציה הראשית (), יש את המשפט:

אוטומטיvariab=fn(2);

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

שים לב שביטוי הלמבה מסתיים בפסיק, בדיוק כמו הגדרת המחלקה או המבנה, מסתיים בפסיק.

בתוכנית הבאה, פונקציה, שהיא ביטוי למבדה המחזירה את הערך 5, היא ארגומנט לפונקציה אחרת:

#לִכלוֹל

באמצעות מרחב שמותשעה (ות;

בָּטֵלאחר(intמספר 1,int (*ptr)(int))

{

intמס '2= (*ptr)(2);

עֲלוּת <<מספר 1<< '' <<מס '2<< ' n';

}


intרָאשִׁי()

{

אחר(4,[](intתפסיק)

{

intתשובה=תפסיק+ 3;

לַחֲזוֹרתשובה;

});


לַחֲזוֹר 0;
}

הפלט הוא:

ארבע חמש

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

פרמטר פונקציית lambda בהגדרת הפונקציה otherfn () הוא מצביע לפונקציה. למצביע יש את השם, ptr. השם, ptr, משמש בהגדרת otherfn () כדי לקרוא לפונקציית lambda.

ההצהרה,

intמס '2= (*ptr)(2);

בהגדרת otherfn (), הוא מכנה את פונקציית lambda עם ארגומנט של 2. ערך ההחזרה של השיחה, '(*ptr) (2)' מפונקציית lambda, מוקצה ל- no2.

התוכנית לעיל מראה גם כיצד ניתן להשתמש בפונקציית lambda בתוכנית הפונקציות החזרה של C ++.

חלקי ביטוי למבדה

החלקים של פונקציית למבדה טיפוסית הם כדלקמן:

[] () {}
  • [] הוא סעיף הלכידה. זה יכול להכיל פריטים.
  • () מיועד לרשימת הפרמטרים.
  • {} מיועד לגוף הפונקציונלי. אם הפונקציה עומדת לבד, היא אמורה להסתיים בפסיק.

לוכדת

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

ההגדרה של פונקציית למבדה שונה מהגדרת הפונקציה הרגילה. ניתן להקצות אותו למשתנה בהיקף הגלובלי; ניתן לקודד את הפונקציה שהוקצתה-למשתנה בתוך פונקציה אחרת. כאשר הוא מוקצה למשתנה היקף גלובלי, הגוף שלו יכול לראות משתנים אחרים בהיקף הגלובלי. כאשר הוא מוקצה למשתנה בתוך הגדרת פונקציה רגילה, הגוף שלו יכול לראות משתנים אחרים בהיקף הפונקציות רק בעזרת פיסקת הלכידה, [].

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

#לִכלוֹל

באמצעות מרחב שמותשעה (ות;

intרָאשִׁי()

{

intתְעוּדַת זֶהוּת= 5;


אוטומטיfn= [תְעוּדַת זֶהוּת]()

{

עֲלוּת <<תְעוּדַת זֶהוּת<< ' n';

};

fn();


לַחֲזוֹר 0;

}

הפלט הוא 5 . ללא השם, id, בתוך [], ביטוי הלמבה לא היה רואה את המזהה המשתנה של היקף הפונקציה הראשי ().

צילום באמצעות הפניה

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

#לִכלוֹל

באמצעות מרחב שמותשעה (ות;

intרָאשִׁי()

{

intתְעוּדַת זֶהוּת= 5; לָצוּףרגל= 2.3; לְהַשְׁחִירצ'= 'ל';

אוטומטיfn= [&תְעוּדַת זֶהוּת,&רגל,&צ']()

{

תְעוּדַת זֶהוּת= 6;רגל= 3.4;צ'= 'ב';

};

fn();

עֲלוּת <<תְעוּדַת זֶהוּת<< ',' <<רגל<< ',' <<צ'<< ' n';

לַחֲזוֹר 0;

}

הפלט הוא:

6, 3.4, ב

אישור ששמות המשתנים בתוך גוף הפונקציה של ביטוי למבדה הם לאותם משתנים מחוץ לביטוי הלמבה.

לכידה לפי ערך

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

#לִכלוֹל

באמצעות מרחב שמותשעה (ות;

intרָאשִׁי()

{

intתְעוּדַת זֶהוּת= 5; לָצוּףרגל= 2.3; לְהַשְׁחִירצ'= 'ל';

אוטומטיfn= [id, ft, ch]()

{

// id = 6; רגל = 3.4; ch = 'B';

עֲלוּת <<תְעוּדַת זֶהוּת<< ',' <<רגל<< ',' <<צ'<< ' n';

};

fn();

תְעוּדַת זֶהוּת= 6;רגל= 3.4;צ'= 'ב';

עֲלוּת <<תְעוּדַת זֶהוּת<< ',' <<רגל<< ',' <<צ'<< ' n';

לַחֲזוֹר 0;

}

הפלט הוא:

5, 2.3, א

6, 3.4, ב

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

ערבוב לכידות

ניתן לערבב לכידה בהתייחסות ולכידה לפי ערך, כפי שמראה התוכנית הבאה:

#לִכלוֹל

באמצעות מרחב שמותשעה (ות;

intרָאשִׁי()

{

intתְעוּדַת זֶהוּת= 5; לָצוּףרגל= 2.3; לְהַשְׁחִירצ'= 'ל'; בולbl= נָכוֹן;


אוטומטיfn= [מזהה, רגל,&צ',&bl]()

{

צ'= 'ב';bl= שֶׁקֶר;

עֲלוּת <<תְעוּדַת זֶהוּת<< ',' <<רגל<< ',' <<צ'<< ',' <<bl<< ' n';

};

fn();


לַחֲזוֹר 0;

}

הפלט הוא:

5, 2.3, B, 0

כאשר כולם נלכדים, הם לפי הפניה:

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

#לִכלוֹל

באמצעות מרחב שמותשעה (ות;

intרָאשִׁי()

{

intתְעוּדַת זֶהוּת= 5; לָצוּףרגל= 2.3; לְהַשְׁחִירצ'= 'ל'; בולbl= נָכוֹן;


אוטומטיfn= [&]()

{

תְעוּדַת זֶהוּת= 6;רגל= 3.4;צ'= 'ב';bl= שֶׁקֶר;

};

fn();

עֲלוּת <<תְעוּדַת זֶהוּת<< ',' <<רגל<< ',' <<צ'<< ',' <<bl<< ' n';


לַחֲזוֹר 0;

}

הפלט הוא:

6, 3.4, B, 0

אם יש ללכוד משתנים מסוימים בהתייחסות ואחרים לפי ערך, אז אחד & ייצג את כל ההפניות, וכל השאר לא יקדם כלום, כפי שמראה התוכנית הבאה:

באמצעות מרחב שמותשעה (ות;

intרָאשִׁי()

{

intתְעוּדַת זֶהוּת= 5; לָצוּףרגל= 2.3; לְהַשְׁחִירצ'= 'ל'; בולbl= נָכוֹן;


אוטומטיfn= [&, id, ft]()

{

צ'= 'ב';bl= שֶׁקֶר;

עֲלוּת <<תְעוּדַת זֶהוּת<< ',' <<רגל<< ',' <<צ'<< ',' <<bl<< ' n';

};

fn();


לַחֲזוֹר 0;

}

הפלט הוא:

5, 2.3, B, 0

שים לב ש & לבד (כלומר, & לא ואחריו מזהה) חייב להיות הדמות הראשונה בסעיף הלכידה.

כאשר כולם נלכדים, לפי ערך:

אם כל המשתנים שיש ללכוד צריכים להילכד לפי ערך, אז רק אחד = יספיק בסעיף הלכידה. התוכנית הבאה ממחישה זאת:

#לִכלוֹל

באמצעות מרחב שמותשעה (ות;

intרָאשִׁי()
{

intתְעוּדַת זֶהוּת= 5; לָצוּףרגל= 2.3; לְהַשְׁחִירצ'= 'ל'; בולbl= נָכוֹן;


אוטומטיfn= [=]()

{

עֲלוּת <<תְעוּדַת זֶהוּת<< ',' <<רגל<< ',' <<צ'<< ',' <<bl<< ' n';

};

fn();


לַחֲזוֹר 0;


}

הפלט הוא:

5, 2.3, A, 1

הערה : = הוא לקריאה בלבד, נכון לעכשיו.

אם יש ללכוד כמה משתנים לפי ערך ואחרים בהתייחסות, אז אחד = ייצג את כל המשתנים שהועתקו לקריאה בלבד, ולשאר כל אחד &, כפי שמראה התוכנית הבאה:

#לִכלוֹל

באמצעות מרחב שמותשעה (ות;

intרָאשִׁי()

{

intתְעוּדַת זֶהוּת= 5; לָצוּףרגל= 2.3; לְהַשְׁחִירצ'= 'ל'; בולbl= נָכוֹן;


אוטומטיfn= [=,&צ',&bl]()

{

צ'= 'ב';bl= שֶׁקֶר;

עֲלוּת <<תְעוּדַת זֶהוּת<< ',' <<רגל<< ',' <<צ'<< ',' <<bl<< ' n';

};

fn();


לַחֲזוֹר 0;

}

הפלט הוא:

5, 2.3, B, 0

שים לב ש = לבד חייב להיות הדמות הראשונה בסעיף הלכידה.

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

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

#לִכלוֹל

באמצעות מרחב שמותשעה (ות;

לְהַשְׁחִיר *תְפוּקָה;


אוטומטיcba= [](לְהַשְׁחִירהַחוּצָה[])

{

תְפוּקָה=הַחוּצָה;

};



בָּטֵלmainFunc(לְהַשְׁחִירקֶלֶט[],בָּטֵל (*ל)(לְהַשְׁחִיר[]))

{

(*ל)(קֶלֶט);

עֲלוּת<<'לתפקיד ראשי'<<' n';

}


בָּטֵלfn()

{

עֲלוּת<<'עַכשָׁיו'<<' n';

}


intרָאשִׁי()

{

לְהַשְׁחִירקֶלֶט[] = 'לפונקציית התקשרות חוזרת';

mainFunc(קלט, cba);

fn();

עֲלוּת<<תְפוּקָה<<' n';



לַחֲזוֹר 0;

}

הפלט הוא:

לתפקוד עיקרי

עַכשָׁיו

עבור פונקציית החזרה

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

סוג נגרר-החזרה

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

#לִכלוֹל

באמצעות מרחב שמותשעה (ות;

אוטומטיfn= [](intתפסיק) -> int

{

intתשובה=תפסיק+ 3;

לַחֲזוֹרתשובה;

};


intרָאשִׁי()

{

אוטומטיvariab=fn(2);

עֲלוּת <<variab<< ' n';


לַחֲזוֹר 0;

}

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

סגירת מעגל

שקול את קטע הקוד הבא:

מבנהCla

{

intתְעוּדַת זֶהוּת= 5;

לְהַשְׁחִירצ'= 'ל';

}obj1, obj2;

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

עם זאת, קידוד הביטוי למבדה כמו המבנה לעיל יוחלפו obj1 ו- obj2 בארגומנטים של הפרמטרים המתאימים. התוכנית הבאה ממחישה זאת:

#לִכלוֹל

באמצעות מרחב שמותשעה (ות;

אוטומטיfn= [](intparam1,intparam2)

{

intתשובה=param1+param2;

לַחֲזוֹרתשובה;

} (2,3);


intרָאשִׁי()

{

אוטומטיאיפה=fn;

עֲלוּת <<איפה<< ' n';


לַחֲזוֹר 0;

}

הפלט הוא 5. הטיעונים הם 2 ו -3 בסוגריים. שים לב כי קריאת הפונקציה לביטוי lambda, fn, אינה דורשת כל טיעון מכיוון שהארגומנטים כבר קודדו בסוף ההגדרה של פונקציית lambda.

סיכום

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

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