Scala概述(四)操作也是對象(2、3)

4.2.    函數也是對象(Functions are Objects

既然方法是值,值是對象,方法當然也就是對象。實際上,函數類型和函數值(注意:指函數本身作爲值——譯註)只不過是相應的類及其實例的語法糖衣。函數類型S=>T等價於參數化類型scala.Function1[S, T],這個類型定義在Scala標準類庫中:

package scala

abstract class Function1[-S,+T] {

def apply(x: S): T

}

       參數超過一個的函數也可類似地定義,一般而言,n-元函數類型:T1T2Tn=>T被解釋爲Functionn[T1T2TnT]。也就是說,函數就是擁有apply方法的對象。例如,匿名函數“+1:x:int=>x+1,就是如下函數Function1的實例:

new Function1[int, int] {

def apply(x: int): int = x + 1

}

反之,當一個函數類型的值被應用於參數之上(也就是調用——譯註)時,這個類型的apply方法被自動插入,例如:對於Function1[S, T]類型的函數pp(x)調用自然擴展爲p.apply(x)

 

4.3. 細化函數(Refining Functions

既然Scala中函數類型是類,那麼也可以再細化成爲子類。以Array爲例,這是一種以整數爲定義域的特殊函數。Array[T]繼承自Function1[int, T],並添加了數組更新、長度等方法:

package scala

class Array[T] extends Function1[int, T]

with Seq[T] {

def apply(index: int): T = ...

def update(index: int, elem: T): unit= ...

def length: int = ...

def exists(p: T => boolean): boolean = ...

def forall(p: T => boolean): boolean = ...

...

}

賦值語句左側的函數調用是存在特殊語法的,他們使用update方法。例如,a(i)=a(i)+1被翻譯成:

a.update(i, a.apply(i) + 1)

Array存取翻譯成方法調用看上去代價比較高,但是Scala中的inlining變換可以將類似於上面的代碼翻譯成宿主系統的原生數組存取。

上述Array類型還定義了existsforall方法,這樣也就不必手工定義了,使用這些方法,hasZeroRow可以如下定義:

def hasZeroRow(matrix: Array[Array[int]]) =

matrix exists (row => row forall (0 ==))

注意上述代碼和相關操作的語言描述的對應性:“test whether in the matrix there exists a row such that in the row all elements are zeroes”(檢測一個矩陣,看看它是否有一行的所有元素都等於0。這裏保留英語原文,因爲原文中使用斜體部分對應於上述代碼的內容,體現兩種語法的對應關係——譯註)。還要注意一點:在上面的匿名方法中,我們略去了參數row的類型,因爲其類型可以被Scala編譯器根據matrix.exists方法推斷出來。

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章