מעוניינים ללמוד עוד על סקאלה? קחו את הקורס מבוא לסקאלה של DataCamp.
סקאלה היא שפת תכנות פונקציונלית שבה יש פונקציות כערכים ברמה ראשונה וגם שיטות, ויש לה גם קווי דמיון וגם הבדלים. גם הפונקציות וגם השיטות הן בלוק של קוד שניתן להשתמש בו מחדש, וגם משמשות לאחסון קוד שחוזר על עצמו במקום אחד, מה שמאפשר קריאת פונקציה לביצוע משימה מסוימת. הן גם מקלות על איתור באגים ושינויים בקוד.
עם זאת, פונקציות הן אובייקטים שמאותחלים במשתנה, אבל שיטות מתחילות עם מילת המפתח 'def' ואחריה שם השיטה, רשימת הפרמטרים, גוף השיטה עם ערך ההחזרה.
הצהרת והגדרת שיטה
התחביר להצהרת והגדרת שיטה בסקאלה הוא כדלקמן:
def 'method_name' ('parameters':'return_type_parameters') : ('return_type_of_method') = { 'method_body' return 'value' }
השיטה בסקאלה מתחילה עם החלקים הבאים:
- 'def': מילת מפתח שמשמשת להצהרת שיטות.
- 'שם_השיטה': הוא שם השיטה שלכם, שהוא במבנה camel case תחתון.
- 'פרמטרים': הם הפרמטרים של השיטה שיכולים להיות ללא פרמטרים או פרמטר אחד בלבד, אבל מופרדים בפסיק כשיש יותר מפרמטר אחד.
- 'סוג_החזרה_של_הפרמטרים': צריך להתאים לפי סוג הנתונים של 'רשימת הפרמטרים' והוא חובה.
- 'סוג_החזרה של_פעולה': הוא אופציונלי, אך בברירת מחדל, 'Unit' מוחזר, אך יכול להיות שהערך יוחזר בעזרת מילת המפתח 'return'.
- סימן ההשמה('='): הוא אופציונלי, ואם ישמש ייעניק את הערך שנחזר ולא להשתמש בו יגרום לפעולה לא להחזיר כלום.
- 'גוף_הפעולה': זה חלק הקוד המקופל בסוגריות '{}' ומכיל את ההגיון הדרוש ואת המשימה או הפעולות המסוימות.
- return: זו מילת המפתח שמשמשת להחזרת הערכים הדרושים וגם להפסקת התוכנית אך נעשית בהדרגה בסקלה.
הפעלת פעולה
הסינטקס להפעלת פעולה בסקלה הוא כך:
method_name(arguments)
ההפעלה של פעולה ניתנת לביצוע באמצעות 'שם_הפעולה', שזהו שם הפעולה המתאים שאתה רוצה לפעול עם הארגומנטים שנשלחים.
פעולה עם ארגומנטים בשם
הפעולה עם ארגומנטים בשם מאפשרת העברת הארגומנט לפרמטרים של הפעולה בזמן ההפעלה של הפעולה, כשכל אחד מהארגומנטים מתאים אחד-אחד לפרמטרים של הפעולה. תראו את הדוגמה שלהלן להעברת הארגומנטים עם הצהרת פונקציה וההגדרה וביחד עם הפעלת הפעולה:
object calculateResult { def funSub(x:Int, y:Int) : Int = { var diff:Int = 0 diff = x - y // return value return diff } def main(args: Array[String]) { // Function call println("Difference of the value is: " + funSub(8,6)); println("Difference of the value is " + funSub(y=6,x=8)); } }
התוכנית שלהלן מספקת את הפלט כך:
ההבדל של הערך הוא: 2
ההבדל של הערך הוא: 2
טעם התוכנית העליונה מכילה אובייקט 'calculateResult', ובתוכו מכילה שיטה בשם 'funSub' עם שני הפרמטרים x ו y המפרידים עם סוג החזרה 'Int,' הסוג הכללי של השיטה הוא 'Int'. זה עוקב על הצהרת ההשמה שמקבלת את ערך החזרה. הסוגריות מסמנות את התחלת גוף השיטה, שם המשתנה 'diff' מופעל עם הערך ההתחלתי של 0. הקריאה לשיטה 'funSub(8,6)' שנעשתה בשיטה העיקרית מתאימה 8 ל'x' ו-6 ל'y,' ובוצעת פעולת החיסור, והערך של 'diff' חוזר ולבסוף מודפס. בדיוק כך, 'funSub(x=8,y=6)' מתאים 6 ל'y' ו-8 ל'x' לפרמטרים בשיטה בזמן הקריאה לשיטה שכאן הסדר לא משנה ובוצעת פעולה דומה וחוזרה והתוצאה מודפסת.
ערכי פרמטרים ברירת מחדל
ניתן לציין ערכי ברירת המחדל עבור פרמטרי השיטה דרך ההתחלתם של הערכים התואמים וניתן להשאיר את הקריאה לשיטה ריקה על ידי לא העברת הארגומנט.
object calculateResult { def funSub(x:Int=9, y:Int=6) : Int = { var diff:Int = 0 diff = x - y // return value return diff } def main(args: Array[String]) { // Function call print( "The final value is: " + funSub() ); } }
התוכנית העליונה מקבלת פלט כזה:
הערך הסופי הוא: 3
ניתן לראות בתוכנית שמופיעה למעלה שיש אובייקט המגדיר 'calculateResult', ובתוכו יש שיטה בשם 'funSub' עם הפרמטרים x ו y, ששניהם מחזירים סוג 'Int', והסוג המחזיר של השיטה הוא 'Int', ומאחריהם משמשת השיטה השמת ערך. הסוגריות מצביעות על התחלת גוף השיטה, שם המשתנה 'diff' מופעל עם הערך ההתחלתי 0. ההתקשרות לשיטה מתבצעת בתוך השיטה הראשית 'main', שם 'funSub()' נקרא ומציבים x כ 9 ו y כ 6, ומבצעת הפעולה, שמעלה את הערך 'diff' להחזרה ולהדפסה.
ארגומנטים באורך משתנה
ארגומנטים באורך משתנה הם הארגומנטים המקבלים מספר גודל של ארגומנטים ויכולים להיות מועברים על ידי המשתמש או הלקוח. הארגומנט האחרון בשיטה מוגדר באמצעות '*' שצריך להתחזק.
object variableArgument { def main(args: Array[String]) { printAll("Scala", "is", "great") } def printAll(strings: String*) { var i : Int = 0; for( value <- strings ){ println(value); i = i + 1; } } }
התוכנית שמופיעה למעלה מציגה פלט כזה:
Scala
היא
גדולה
ניתן לראות בתוכנית שמופיעה למעלה שיש אובייקט 'variableArgument' עם שיטות 'printAll', שבהן מוגדרים ארגומנטים באורך משתנה 'String*', בסוף, ובקריאה לשיטה ניתן להעביר רשימת מחרוזות. הרשימה של המחרוזות שהועברה מתגלה במעגל ומוצגת כפלט בתוך הפעולה הראשית.
שיטת השיבור
הרקורסיה היא הטכניקה שמשמשת בתכנות פונקציונלי בה הבעיה נפתרת על ידי פיצולה חוזר וחוזר לתת בעיות קטנות יותר, שדומות לבעיה המקורית. הבעיות הקטנות נפתרות, והפתרונות שלהן מיושמים על מנת לקבל פתרונות לבעיה המקורית. על כן, זה נקרא בעיה של חלוקה וכיבוס או ירידה וכיבוס, שגורמת לקוד להיות נקי ואלגנטי. בעת כתיבת פונקציה רקורסיבית, יש לשקול שני נקודות במחוון. אלו הם:
מקרה בסיס: ייתכן ויהיו יותר ממקרה בסיס אחד בפונקציה שצריך למצוא אחרת עשויה להביא לרקורסיה אין סוף. יש להיות לבעיה פתרון, כלומר הפורמה הפשוטה של הפלט או הפתרון הניתן להשגה ללא רקורסיה.- מקרה רקורסיבי: המקרה בו מופעלת הפונקציה הרקורסיבית, כלומר נעשות קריאות רקורסיביות. הצפיפות המרכזית של הבעיה היא שבכל קריאה רקורסיבית, גודל הבעיה חייב להקטין כלומר הבעיה חייבת להתחלק לבעיות קטנות יותר עד שתגיע למקרה בסיס. בסופו של דבר, עליך לשלב את הפתרון כדי לקבל את הבעיה המרכזית, שזהו גישת חלוקה וכיבוס.
גורם הפקוריאלית של כל מספר נתון הוא n! ניתן להביעו באופן מתמטי כדלהלן:
בנוסף, ניתן להפוך את המונים (n-1).(n-2)…3.2.1 ל-(n-1)! לכן, גורם הפקוריאלית של כל מספר נתון הוא תמיד n*(n-1)!
עכשיו תוכל לראות את הדרך הרקורסיבית לפתרון הבעיה.
object factorialDemo { def main(args: Array[String]) { for (i <- 1 to 5) println( "Factorial of " + i + ": = " + factorial(i) ) } def factorial(n: Int): Int = { if (n <= 1) return 1 else return n * factorial(n - 1) } }
התוכנה העלויה תעבוד כך:
מסת 1: = 1
מסת 2: = 2
מסת 3: = 6
מסת 4: = 24
מסת 5: = 120
אתם יכולים לראות מעל המקום בו יש אובייקט בשם 'factorialDemo' ובתוכו, יש פונקציית 'main' שמורכבת בלולאה שמתחילה ומסתיימת חמש פעמים וכן כוללת הצגה בפונקציית 'factorial', בה הפונקצייה הרצינית עושה התקשורת חזרתית, כלומר, n עד חמש פעמים. היא מפסיקה במקרה הבסיס כשn נעשה פחות או אותו מספר של 1, והתוצאה נשארה ומדפיסה.
פונקציית אנונימית
פונקציית אנונימית היא הגדרה קלה של פונקצייה שאין לה שם וידועה ב-Scala כfunction literal (פונקצייה מונחת).
השקל עם דוגמא לפונקציית אנונימית הוא כך:
- השקל הראשון ודוגמא לפונקציית אנונימית היא:
שקל:
('first_variable':'data_type', 'second_variable':'data_type') => "certain_expression"
דוגמא:
(var1:String:var2:String) => var1 + var2
או
- השקל השני ודוגמא לפונקציית אנונימית היא:
שקל:
(_:'data_type')operator(_'data_type')
דוגמא:
(_:String)+(_:String)
השקל הראשון מראה שהתוצאה אחרי "=>" מוערכת לערך מסויים, בעוד רשימת המשתמשים לפני "=>" מוערכת להערכת התוצאה.
השקל השני מתפקד כמו מקו
זה תוכנה של פונקציה אנונימית המופיעה מתחת:
object anonymousDemo { def main(args: Array[String]) { var function1 = (var1:Int, var2:Int) => var1 + var2 var function2 = (_:Int) + (_:Int) // function call println(function1(5, 5)) println(function2(7, 3)) } }
Initializing Scala interpreter ... Spark Web UI available at http://DESKTOP-03TH7J0:4040 SparkContext available as 'sc' (version = 2.4.3, master = local[*], app id = local-1566986265958) SparkSession available as 'spark' <console>:10: error: unbound placeholder parameter var function2 = {_:Int} + {_:Int} ^ <console>:10: error: unbound placeholder parameter var function2 = {_:Int} + {_:Int} ^
התוכנה העליונה מפרידה את הפלט כך:
10
10
ניתן לראות שלמעלה יש אובייקט בשם 'anonymousDemo' עם הפונקציה 'main' שכוללת שתי פונקציות אנונימיות. הן הן סינטקטית שונות אבל יכולות להפיק את אותו תוצאה, היכן ש'function'1 מתוחכם בקבלת פרמטרים מקריאת הפונקציה בעת שהיא נקראת — מעבירה את הערכים 5 ו-5, שמופיעים כתוצאה שמודפסת כ-10 בעוד 'function2' גם נקראת עם העברת 7 ו-3 שם היא מקבלת את הערך פעם אחת, היכולה לקבל כל 'Integer' חוקי. במקרה שלך, תבצעי חיבור ותפרקי את התוצאה.
מסקנה
מזל טוב, סיימתם לקרוא את ההדרכה הזו.
ישנם נושאים מתקדמים רבים בסקלה כמו פונקציות רב-דרגיות, פונקציות עטופות, פונקציות קוריינג, ועוד.
הפניה:
סיור בבסיסי סקלה
סקלה | פונקציות – בסיסים
סקלה – פונקציות
פונקציות אנונימיות בסקלה
תסתכלו על קורס הקדמה לסקלה של DataCamp.
Source:
https://www.datacamp.com/tutorial/basic-functions-methods-scala