今天我們來談函式
當程式變大時,我們會需要某種方式來把它們分得更小塊、更易於管理。
Scala提供了一種:把程式分割成函式
定義函式最常用的方式就是作為某個物件的成員,稱之為方法(method)
import scala.io.Source
object LongLines{
def readFile(filename: String, width: Int) = {
val source = Source.fromFile(filename)
for (lines <- source.getLines())
readLine(filename, width, line)
}
private def readLine(filename: String, width: Int, line: String) = {
if (line.length > width)
println(filename + ":" + line.trim)
}
}
這裡有兩個方法,用來讀取檔案並輸出超過指定長度的行
首先,readFile
接收兩個參數:檔案名以及寬度
再來它從檔案名創建了一個source物件
接下來的for迴圈從source呼叫getLine
回傳每次從檔案讀取的一行
for迴圈內會呼叫readLine
方法來處理每一行文字
readLine
這邊是私有方法,接收三個參數分別是檔案名、寬度、行
if判斷式內,如果行的長度大於給定的寬度,便會輸出檔案名、冒號跟該行文字
在上面例子的readLine
方法的建構為我們展示了函式程式設計風格的一個重要原則:
Programs should be decomposed into many small functions that each do a well-defined task.
意思是,程式應該被分解為許多小函式,而每個小函式都會執行一個定義好的任務。
所以Scala在這邊提供了一種方法:
def readFile(filename: String, width: Int) = {
def readLine(filename: String, width: Int, line: String) = {
if (line.length > width)
println(filename + ":" + line.trim)
}
}
val source = Source.fromFile(filename)
for (lines <- source.getLines())
readLine(filename, width, line)
原先的例子在這邊重新建構
把readLine私有方法轉換成readFile裡的區域函式
另外有個細節,這裡的readLine方法既然被定義在readFile內部,用到的參數filename及width完全沒變,所以可以直接使用外部readFile的參數當作readLine方法的參數,如下:
def readFile(filename: String, width: Int) = {
def readLine(line: String) = {
if (line.length > width)
println(filename + ":" + line.trim)
}
}
val source = Source.fromFile(filename)
for (lines <- source.getLines())
readLine(filename, width, line)
這樣簡潔的語法在我們接下來要介紹的First-class function將會非常強大。
今天就先介紹到這邊