שאלת ראיונות עבודה פשוטה על פונקציות שנתקלתי בה לא מזמן ואפילו הצליחה לבלבל חבר - מה ההבדל בין שתי שורות הקוד הבאות, וכיצד נכתוב פונקציה add שתגרום לשתיהן לעבוד במכה אחת:
add(2, 5); // 7
add(2)(5); // 7
השאלה מעניינת כי היא עוזרת לנו להבין משהו על ערכי החזר של פונקציות ועל רעיון שנקרא Currying. אבל קודם קצת הסבר על שתי צורות ההפעלה:
בשורה הראשונה אני פשוט מפעיל את הפונקציה עם שני פרמטרים ומצפה לקבל חזרה את סכומם.
בשורה השניה יש כבר שתי הפעלות. כאן אנחנו רואים שאם העבירו רק פרמטר אחד לפונקציה אז אנחנו צריכים להחזיר פונקציה חדשה שתמיד תוסיף את ערך פרמטר זה לפרמטר שהיא מקבלת ומחזירה את התוצאה. דרך אחרת לכתוב את השורה השניה תהיה:
const add2 = add(2);
// now add2 is a new function
const result = add2(7);
// now result is 7
דרך קלה לכתוב את הקוד היא להתמקד בעובדה שאנחנו מדברים על פונקציה שמקבלת שני פרמטרים ולהסתכל ממש על מספר הפרמטרים, או במילים אחרות לכתוב את הקוד הבא:
function add(x, y) {
if (arguments.length === 2) {
return x + y;
} else if (arguments.length === 1) {
return y => add(x, y);
}
}
console.log(add(2, 5));
console.log(add(2)(5));
עוד צעד קדימה יכול להיות להוציא החוצה את החלק בקוד שמתעסק בהפעלה חלקית של הפונקציה לפונקציה נפרדת, למשל נוכל לקרוא לה partialify:
function partialify(f) {
const requiredArgsCount = f.length;
return function(...args) {
if (args.length === requiredArgsCount) {
return f(...args);
} else {
return f.bind(null, ...args);
}
}
}
const add = partialify(function add(x, y) {
return x + y;
});
console.log(add(2, 5));
console.log(add(2)(5));
עכשיו אפשר להפעיל את הקוד גם על מקרים מתוחכמים יותר אבל שימו לב שהפיתרון עדיין מוגבל להפעלה חלקית אחת בלבד לפונקציה, כלומר הקוד הבא לא עובד:
const add = partialify(function add(x, y, z) {
return x + y + z;
});
console.log(add(2)(5)(7));
נסו לראות שאתם מבינים למה, ואם כן נסו לתקן את הקוד של partialify כדי שכן יעבוד גם במקרה הכללי ביותר. הצלחתם? מוזמנים לשתף את הפיתרונות בתגובות.
נ.ב. את התרגיל לקחתי מהדף הזה שכולל רשימה ארוכה וטובה של שאלות ראיונות עבודה למתכנתי Front End. אם אתם אוהבים כאלה משחקים שווה להעיף שם מבט גם.