שיחה:תכנות פונקציונלי

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

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

אריק1111 - שיחה 18:27, 19 בדצמבר 2011 (IST)תגובה

אני אתן לך דוגמה משפת פייתון (שהיא לא לגמרי פונקציונלית אבל מספיק קרובה):
def apply(f, x, y):
    return f(x, y)
הגדרנו פונקציה המקבלת כפרמטר פונקציה ושני משתנים, ומחזירה את תוצאת הפעלת הפונקציה על המשתנים. לדוגמה:
apply(divmod, 7, 3)
תחזיר את הזוג (2,1) שהוא (השארית של החלוקה של 7 ב-2, תוצאת החלוקה). בדיוק מה שהיתה מחזירה הקריאה (divmod(7,3.
במקרה הזה זה לא מאוד מועיל, כי זאת דוגמה בסיסית. אפשר ליצור בדרך הזאת הרבה דברים מורכבים למדי בצורה נוחה, למשל אם יש לך שתי פונקציות ואתה רוצה לקבל פונקציה אחרת שהיא תוצאת ההרכבה שלהם. לא נתתי את הדוגמה הזאת כי הסינטקס שלה יהיה טיפ-טיפה מורכב יותר בפייתון. בשפת ML, עם זאת, הדוגמה תהיה פשוטה:
fun comp(f, g) = f o g;
הפונקציה מקבלת זוג פונקציות כפרמטר, ומחזירה פונקציה שלישית, שהיא תוצאת ההרכבה שלהן (בעזרת האופרטור 'o'). --אלעזר - שיחה 01:02, 21 בדצמבר 2011 (IST)תגובה
תודה על ההסבר. אם אינני טועה מה שאתה אומר מבוצע בc ע"י שליחת מצביע לפונקציה?אריק1111 - שיחה 11:45, 21 בדצמבר 2011 (IST)תגובה
מה שאני אומר מקורב ב-C ע"י מצביעים לפונקציה. ב-C אין שום דרך ליצור פונקציה "על הדרך" - פונקציה אנונימית, או פונקציית למבדא. זה כלי חזק מאוד של שפות פונקציונליות. כמו כן הדוגמה האחרונה (הרכבת פונקציות) לא ניתנת לביצוע בשפת C. בכלל, לא ניתן ב-C ליצור פונקציה בתוך פונקציה (מסיבות טובות מאוד - שיקולי יעילות, בהן היא מצטיינת - אבל על המתכנת זה לא מקל), וכל הפונקציות מוגדרות היטב בזמן הידור הקוד. אם למשל (וזאת לא דוגמה טובה לתכנות פונקציונלי בגלל תוצאות הלוואי של הדפסה) אני רוצה להפוך פונקציה למתועדת - "לעטוף אותה" כך שכל קריאה אליה תירשם (שוב פייתון):
def wrap(f, name):
    def wrapped(x,y):
        print(name, "called")
        res = f(x,y)
        print("the result is", res)
    return wrapped
השימוש בה, לדוגמה (שים לב ליצירה של פונקציה בתוך ביטוי, בקלות רבה, בעזרת המילה lambda):
wrapped_addition = wrap(lambda x,y: x+y, "add")
wrapped_addition(2,3)
באותה מידה יכולתי ליצור פונקציה עוטפת "גנרית" המקבלת פונקציה אחרת להפעיל לפני ואחרי כל קריאה לפונקציה הראשית, וכן הלאה.
כל הדוגמאות שהבאתי כאן הן דוגמאות פשוטות יחסית, "צעצוע", אם כי לעטוף קריאה לפונקציה זאת דרך יעילה למדי לבחון קוד - למשל, למדוד משך ריצה של כל קריאה. דוגמאות רציניות יותר יהיו גם מורכבות יותר, ולעיתים קשות להבנה מכדי להשתמש בהן להסבר.
בתכנות מונחה עצמים, יצירה של עצם בר-קריאה (callable), למשל ב++C אובייקטים עבורם מועמס אופרטור הקריאה לפונקציה, היא פעולה דומה מאוד מאוד לדברים שעשינו כאן, עם יתרונות וחסרונות.
הערה אחרונה: כמו שמופיע בערך, פייתון היא לא שפה פונקציונלית, ואני נעזר בה רק כי התחביר שלה קריא יותר למי שמגיע מבחוץ מאשר שפות פונקציונליות אמיתיות. --אלעזר - שיחה 13:06, 21 בדצמבר 2011 (IST)תגובה

דוגמה לא טובה: "הסרת ערכים כפולים ומיון ברשימה"[עריכת קוד מקור]

הפיסקה "הסרת ערכים כפולים ומיון ברשימה" לא מוסיפה ואף מטעה. זו אינה דוגמה מובהקת לתכנות פונקציונאלי. למעשה מדובר על הפעלת פונקציות אחת על תוצאת השניה. לדעתי זה תיכנות אימפרטיבי מובהק ולכן מטעה כאילו זו הכוונה בתכנות פונקציונאלי. הדוגמה שאני יכול לחשוב מ C# היא רשימת ארועים להפעלה, שממש מוסיפים לה פונקציות משל היו אוביקטים לכל דבר. אני זוכר במעורפל עוד מקרים של העברת פונקציות כפרמטרים או השמה לתוך משתנים אך זו לא השפה שאני מומחה בה ואעדיף להשאיר את המלאכה לאחרים.יגאל1 - שיחה 10:18, 22 ביולי 2013 (IDT)תגובה

אתה צודק שזאת לא דוגמה טובה; הסרתי אותה. אבל "הפעלת פונקציות אחת על השניה" היא דווקא כן חלק מהותי מתכנות פונקציונלי. זה פשוט אחד החלקים שנטמעו מזמן עמוק בתוך שפות התכנות האימפרטיביות הנפוצות. תחשוב איך אמורים למממש דבר כזה עם פרוצדורות בפסקל - אז זה היה תכנות אימפרטיבי. --אלעזר - שיחה 20:19, 23 ביולי 2013 (IDT)תגובה
 List<string> list2 = list1.Distinct().OrderBy(x => x.TrimStart()).ToList();
הביטוי OrderBy(x => x.TrimStart() הוא תחשיב למדא מובהק, שבו פונקציה מקבלת כפרמטר פונקציה אחרת. בשאר הדוגמה שבו פונקציה מופעלת על האחרת, יש שימוש שמדגים תחביר פונקציונלי ב-composition (הרכבת פונקציות). ניתן לראות כי לבסוף כל התוכן מועבר לפונקציה שממירה את התוצאה ל-LIST מבלי שיועבר לה תוכן בפרמטר כלשהו. בכל אופן, אם תחשיב למדא ב-C# איננו תכנות פונקציונאלי אז באמת ישנה שאלה גדולה מה בC# הוא תכנות פונקציונאלי. --אפי ב.התחברו ל♥18:10, 7 באוגוסט 2013 (IDT)תגובה
הביטוי הראשון שאמרת הוא אכן דוגמה לתכנות פונקציונלי, אבל הוא לא מצדיק את הסעיף כולו. השאר זה הרכבת פונקציות, וזה דבר שכל שפה בעצם תומכת בו; זה לא מה שנקרא "תכנות פונקציונלי" ולא מסביר דבר. "מבלי שיועבר לה תוכן בפרמטר כלשהו" - במקרה הזה מדובר בסך הכל בסינטקס אחר להפעלת פונקציה: לפונקציה ToList מועבר פרמטר יחיד, שהוא תוצאת הביטוי הקודם כולו (וזה שיש דיספאצ' דינמי זה עניין שקשור לתכנות מונחה עצמים בכלל). במקום לשחזר מחיקות, עדיף להביא דוגמה מתאימה יותר. אירועים הם דוגמה אפשרית, אבל בשביל זה יש את תכנות מונחה-אירועים. התחביר של Linq הוא דוגמה אחרת לדברים שנלקחו מתכנות פונקציונלי, וגם הוא לא משהו שהייתי שם בערך הזה. כאן צריכות להיות בעיקר דוגמאות משפות כמו ML, Haskell, Lisp, Scheme, CaML וכדומה. צריך לשים דוגמאות ל Map, Filter, Reduce, בתור התחלה. --אלעזר - שיחה 13:47, 9 באוקטובר 2013 (IDT)תגובה
קודם כל טוב שהתעוררת אחרי חודשיים. אם היית משיב קודם, היה אפשר לנהל דיון ולא הייתי נאלץ לשחזר את הערך. מעבר לכך גם אתה מודה שהביטוי הראשון הינו דוגמה לתכנות פונקציונלי. אז אפשר היה להשאיר ולא למחוק את כל הדוגמה בפעם השנייה. מעשה שלדעתי גובל בעריכה אגרסיבית ובחוסר התחשבות. אני לא מפריע לך לשים בערך דוגמאות מכל השפות שציינת, ובכל היבט שתרצה, ומבקש שלא תפריע לי לשים דוגמה בעניין משפת C#, שפה שבה אני עובד. אדרבה יש מקום גם לאלו וגם לאלו, ובמיוחד כאשר הערך כה רזה. לטעמי העריכות שלך (גם בערכים אחרים כמו C# אגרסיביות מדי). כדאי גם לך להתחשב קצת במאמץ ובעבודה של אחרים. תודה. --אפי ב.התחברו ל♥23:53, 9 באוקטובר 2013 (IDT)תגובה

לא מדויק ואף שגוי[עריכת קוד מקור]

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

נראה שיש כאן חוסר דיוק, כיוון שהפרדיגמה הפונקציונלית מתבססת על רקורסיה תכנותית, וכאשר פונקציה קוראת לעצמה בכל איטרציה (במקום לולאה פשוטה), בכל קריאה נשמרת כתובת החזרה ואוסף המשתנים המקומיים של הפונקציה במחסנית, כך שיש כאן תקורה גבוהה גם בזיכרון וגם בזמן הריצה. ואמנם כמו שכתוב שבערך רקורסיה ששפות פונקציונליות בפרט מבצעות אופטימיזציה של קריאות רקורסיביות והופכות את הקוד הפונקציונלי לקוד לינארי המבוצע בפועל באמצעות לולאות. ואם זו הסיבה לכך שאין הבדל ניכר בין השיטות השונות בזמן עיבוד וזיכרון יש לציין זאת. --אפי ב.התחברו ל♥13:14, 11 באוקטובר 2013 (IDT)תגובה

השקילות המדוברת היא מה שנקרא "שקילות טיורינג", והיא מוגדרת בין המודלים התיאורטיים - תחשיב למבדא ומכונת טיורינג. מבחינה מתמטית, לכל תוכנית בתחשיב למבדא מסוים ניתן להגדיר מכונת טיורינג שקולה (מכונת טיורינג = אלגוריתם) במובן ששניהם מחשבים את אותה פונקציה; אותה טענה נכונה גם לכיוון השני. מהתגלית הזאת (ודומותיה) הגיעה התזה של צ'רץ' וטיורינג. השקילות הזאת לא מתייחסת כלל לענייני יעילות (גם לא אסימפטוטיים), כך שאין להם מקום בחלק התיאורטי למעט ההבהרה הזאת עצמה. הנקודות שציינת הן פרטי מימוש שאינם רלוונטיים לפסקה הזאת. --אלעזר - שיחה 13:52, 11 באוקטובר 2013 (IDT)תגובה

עמוד מצוין[עריכת קוד מקור]

הסבר מקיף, ברור ומנוסח הרבה יותר טוב מרוב הדפים שראיתי או כתבתי.. עמוד מצוין Jona1357 - שיחה 20:24, 9 בספטמבר 2020 (IDT)תגובה

עמוד מצוין[עריכת קוד מקור]

הסבר מקיף, ברור ומנוסח הרבה יותר טוב מרוב הדפים שראיתי או כתבתי.. עמוד מצוין Jona1357 - שיחה 20:24, 9 בספטמבר 2020 (IDT)תגובה