Scala學習筆記 函式式程式設計

2021-08-27 11:58:27 字數 4870 閱讀 1237

在函式式程式設計中,函式式第一等級的值,就像資料變數的值一樣,你可以從函式中組合形成新函式(如`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 將乙個函式作為值傳遞給另乙個函式 在...