Scala 中函數與方法的基础

對Scala有興趣學習嗎?來试试看DataCamp的Scala入門課程。

Scala是一種函數式程式語言,它同時將函數和方法作為第一類值,並且有類似和不同的地方。函數和方法都是一個可重用的代碼區塊,也用於將重複的代碼存放在一個地方,這使得通過函數調用來執行特定的特定任務。它們還使代碼更易於除錯和修改。

然而,函數是一個在變量中初始化的物件,但方法從 ‘def’ 關鍵字開始,後面接方法名稱、參數列表和带有返回值的函數體。

方法宣告和定義

Scala中方法宣告和定義的語法如下:

def 'method_name' ('parameters':'return_type_parameters') : ('return_type_of_method') = { 'method_body' return 'value' }

Scala中的方法從以下部分開始:

  1. ‘def’: 用來宣告方法的关键字。
  2. ‘method_name’: 是您的方法名稱,該名稱為小驼峰命名法。
  3. ‘parameters’: 是方法的參數,可能沒有參數或只有一个參數,但當有多於一個參數時,它們之間的分隔符是逗號。
  4. ‘return_type_of_parameters’: 需要與 ‘parameters_list’ 的數據類型匹配,並且是強制的。
  5. ‘return_type_of_method’: 是可選的,但在預設情況下,會返回 ‘Unit’,但值可以用 ‘return’ 關鍵字返回。
  6. 賦值符號(‘=’):是可選的,如果使用它將賦值返回值,而不使用它則會使方法不返回任何東西。
  7. ‘method_body’:是大括號 ‘{}’ 內的代碼塊,包含必要的邏輯或特定任務或操作。
  8. return:是用於返回所需值並終止程序的關鍵字,但在 Scala 中很少使用。

方法調用

Scala 中方法調用的語法如下:

method_name(arguments)

方法調用可以通過 ‘method_name’ 快速完成,這是您想要調用的對應方法的名稱,並帶有傳遞的參數。

帶有命名參數的方法

帶有命名參數的方法允許在方法調用時將參數傳遞給方法的參數,每個參數都逐一與方法參數匹配。以下是帶有函數聲明和定義以及方法調用的例子:

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

以下是您提供的文本的 Traditional Chinese 翻譯,我將按照您的要求僅返回翻譯後的文本,並保持您自定义的分隔符不變。

上述程序包含一個名為 ‘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。方法呼叫是在主方法內進行的,其中「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; } } }

上述程式 Output 如下:
Scala
is
great

您可以看到上述程式包含一個「variableArgument」物件和「printAll」方法,該方法最後一個可變長度參數為「String*」,在呼叫方法時可以傳入一個字符串列表。傳入的字符串列表會被循覽,並在主要函數內作為輸出展示。

遞迴函數

遞迴是函數式程式設計中使用的技巧,透過不斷將問題分解為較小的子問題來解決問題,這些子問題與原始問題相似。這些較小的問題被解決後,它們的解決方案被應用於得到原始問題的解決方案。因此,它被稱為分割征服或減少征服問題,這使得代碼保持清晰和優雅。當编写遞迴函數時,需要嚴格考慮兩個點。它們是:

  • 基礎情況:函數中可能存在多個基礎情況,需要找出來,否則可能導致無窮遞迴。它需要有一個解決方案,即不需要遞迴即可實現的輸出或解決方案的簡單形式。
  • 遞迴情況:適用遞迴函數的情況,即進行遞迴調用。問題的主要核心在於,在每次遞迴調用中,大小需要減小,即問題需要被分解為更小的子問題,直到達到基礎情況。最後,您組合這些解決方案來解決主要問題,這稱為分割征服方法。

任何給定數字的階乘是n! 它可以用數學方式表示如下:

n! = n.(n-1).(n-2)…3.2.1

同樣,您可以將項目(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中被稱為函數文字

匿名函數的語法及示例如下:

  • 匿名函數的第一種語法及示例:

語法:

('first_variable':'data_type', 'second_variable':'data_type') => "certain_expression"

示例:

(var1:String:var2:String) => var1 + var2

  • 匿名函數的第二種語法及示例:

語法:

(_:'data_type')operator(_'data_type')

示例:

(_:String)+(_:String)

第一種語法顯示,”=>”後面的表達式計算出一個特定的值,而”=>”前面的變量列表用於計算表達式。

上述的第二種語法像是一個佔位符,它只接受一次 ‘wild card’ 字符的值,然後運算符在它們之間進行運算。

以下是一個匿名函數的示例:

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’。在您的案例中,進行加法操作並輸出結果。

結論

恭喜您读完本教程。

Scala中有很多進階主題,如高阶函數、嵌套函數、柯里化函數等。

參考資料:
TOUR OF SCALA BASICS
Scala | 函數 – 基礎
Scala – 函數
Scala中的匿名函數

查看DataCamp的Scala基礎简介課程。

Source:
https://www.datacamp.com/tutorial/basic-functions-methods-scala