在函式式程式設計中,函式式第一等級的值,就像資料變數的值一樣,你可以從函式中組合形成新函式(如`tan(x)=sin(x)/cos(x))`,可以將函式賦值給變數,也可以將函式作為引數傳遞給其它函式,還可以將函式作為其它函式的返回值。
當乙個函式採用其它函式作為變數或返回值時,它被稱為高階函式。
deffactorial
(i: int): long =
fact(i, 1)
} (0 to 5) foreach (i => println(factorial(i)))
var sum = (1 to 5) filter (_ % 2 == 0) map (_ * 2) reduce (_ + _)
var fact = (1 to 5) filter (_ > 4) map (_ * 2) reduce (_ * _)
print(sum)
print(fact)}
閉包
//閉包
var factor =
2 val multiplier = (i: int) => i * factor
var b = (1
to10) filter (_ >
4) map multiplier reduce (_ * _)
println(b)
3var c = (1
to10) filter (_ >
println(c)
偏函式
偏作用函式是乙個表示式,帶部分而非全部引數列表的函式。返回值是乙個新函式,新函式負責攜帶剩下的引數列表。 偏函式則是帶引數的函式,並未對該型別的所有值都有定義。偏函式的字面量語法由包圍在花括號中的乙個或多個case語句構成:
object
extends
def cat1(s1: string)(s2: string) = s1 + s2
//偏應用函式
val hello = cat1("hello ") _
println(hello("world"))
println(cat1("hello ")("world"))
//偏應用函式
def add(x: int, y: int) = x + y
val addone = add(1, _: int)
println(addone(4)) // 5
println(addone(6)) // 7
val inverse:partialfunction[double, double] =
println(inverse(2.0))
}
curry化的函式
curry將乙個帶有多個引數的函式轉換為一系列函式,每個函式都只有乙個引數
package base.functiont
object
extends
def add(x: int, y: int) = x + y
//add函式柯里化之後:
// def add(x: int) = (y: int) => x + y
//簡化為
// def add(x: int)(y: int) = x + y
val add1 = (add _).curried
println(add1(2)(3)) // 5
println(add1(2) ) // 7
def multiplier(i: int)(factor: int) = i * factor
val byfive = multiplier(5) _
val byfour = multiplier(4) _
println(byfive(5))
println(byfour(5))
def map[a, b](xs: list[a])(func: a => b) = xs.map
// list[string] = list(11, 21, 31)
map(list(1, 2, 3))
}
方法與函式
方法:方法指的是定義在類中的方法
函式:函式在scala中代表1個型別和乙個物件,方法卻不會,方法只會出現在類中。
def max(x: int, y: int): int = if (x > y) x else y
def max = (x: int, y: int) => if (x > y) x else y
兩者都定義為「方法(method)」,但後者返回了乙個函式(function)型別。因此,後者常常也被習慣地稱為函式(function)
。首先,它們兩者可以具有相同的呼叫形式:max(1, 2)。但對於後者,呼叫過程實際上包括了兩個子過程。
其次,兩者獲取函式值的方式不同。後者可以直接獲取到函式值,而對於前者需要執行η擴充套件才能取得等價的部分應用函式。
val f =max _
此時,f也轉變為(int, int) => int的函式型別了。實施上,對於上例,η擴充套件的過程類似於如下試下。
val f = new (int, int) => int
val與def
def用於定義方法,val定義值。對於「返回函式值的方法」與「直接使用val定義的函式值」之間存在微妙的差異,即使它們都定義了相同的邏輯。例如:
val max = (x: int, y: int) =>
if (x > y) x else y
def max = (x: int, y: int) =>
if (x > y) x else y
語義差異
雖然兩者之間僅存在一字之差,但卻存在本質的差異。
def用於定義「方法」,而val用於定義「值」。
def定義的方法時,方法體並未被立即求值;而val在定義時,其引用的物件就被立即求值了。def定義的方法,每次呼叫方法體就被求值一次;而val僅在定義變數時僅求值一次。
例如,每次使用val定義的max,都是使用同乙個函式值;也就是說,如下語句為真。
max
eqmax
// true
而每次使用def定義的max,都將返回不同的函式值;也就是說,如下語句為假。
max
eqmax
// false
其中,eq通過比較物件id實現比較物件間的同一性的。
型別引數
val代表了一種餓漢求值的思維,而def代表了一種惰性求值的思維。但是,def具有更好可擴充套件性,因為它可以支援型別引數。
def max[t : ordering](x: t, y: t): t = ordering[t].max(x, y)
lazy惰性
def在定義方法時並不會產生例項,但在每次方法呼叫時生成不同的例項;而val在定義變數時便生成例項,以後每次使用val定義的變數時,都將得到同乙個例項。
lazy的語義介於def與val之間。首先,lazy val與val語義類似,用於定義「值(value)」,包括函式值。
lazy val max = (x: int, y: int) =>
if (x > y) x else y
其次,它又具有def的語義,它不會在定義max時就完成求值。但是,它與def不同,它會在第一次使用max時完成值的定義,對於以後再次使用max將返回相同的函式值。
引數傳遞
scala存在兩種引數傳遞的方式。
def and(x: boolean, y: boolean) = x && y
對於如下呼叫語句:
and(false, s.contains("horance"))
表示式s.contains("horance")
首先會被立即求值,然後才會傳遞給引數y;而在and函式體內再次使用y時,將不會再對s.contains("horance")
表示式求值,直接獲取最先開始被求值的結果。
傳遞函式
將上例and
實現修改一下,讓其具有函式型別的引數。
def and
(x: () => boolean, y: () => boolean) = x
() && y
()
其中,() => boolean
等價於function0[boolean]
,表示引數列表為空,返回值為boolean的函式型別。
呼叫方法時,傳遞引數必須顯式地加上() =>的函式頭。
and
(() => false, () => s.contains("horance"))
此時,它等價於如下實現:
and(new function0[boolean] , new function0[boolean]
def and
()
按名傳遞
因此,scala提供了另外一種引數傳遞的機制:按名傳遞。按名傳遞略去了所有()
語法雜訊。例如,函式實現中,x與y不用顯式地加上()便可以完成呼叫。
def and(x: => boolean, y: => boolean) = x && y
其次,呼叫點使用者無需構造() => r
的函式值,但它卻擁有延遲初始化的功效。
and(false, s.contains("horance"))
SCALA函式式程式設計
建立乙個自定義列表 如何建立乙個註腳 注釋也是必不可少的 katex數學公式 新的甘特圖功能,豐富你的文章 uml 圖表 flowchart流程圖 匯出與匯入 scala的語法規定,將函式賦值給變數時,必須在函式後面加上空格和下劃線 正常宣告乙個帶有乙個字串型別引數,並返回unit型別的方法 sca...
Scala函式式程式設計
知識點1.scala的柯里化技術,允許將接受多個引數的函式,轉變為接受單一引數的函式 2.柯里化的作用可以允許使用者自建控制結構 object demo03 f1 a int,b int int def f11 a int b int f11 a int b int int def f2 a int...
Scala函式式程式設計
package com.yz6 import scala.collection.mutable.arraybuffer object test 定義乙個函式 軀殼 靈魂 def function0 name string unit println 你好 name 將乙個函式作為值傳遞給另乙個函式 在...