高階函數(shù)
在數(shù)學(xué)和計(jì)算機(jī)科學(xué)中纯出,高階函數(shù)是至少滿足下列一個(gè)條件的函數(shù):
- 接受一個(gè)或多個(gè)函數(shù)作為輸入
- 輸出一個(gè)函數(shù)
在數(shù)學(xué)中它們也叫做算子(運(yùn)算符)或泛函。微積分中的導(dǎo)數(shù)就是常見的例子敷燎,因?yàn)樗成湟粋€(gè)函數(shù)到另一個(gè)函數(shù)暂筝。
高階函數(shù)的例子
假設(shè)有一個(gè)函數(shù)對(duì)給定兩個(gè)數(shù)區(qū)間中的所有整數(shù)求和:
def sumInts(a: Int, b: Int): Int =
if(a > b) 0 else a + sumInts(a + 1, b)
如果現(xiàn)在要求連續(xù)整數(shù)的平方和:
def square(x: Int): Int = x * x
def sumSquares(a: Int, b: Int): Int =
if(a > b) 0 else square(a) + sumSquares(a + 1, b)
如果要計(jì)算2的冪次的和:
def powerOfTwo(x: Int): Int = if(x == 0) 1 else 2 * powerOfTwo(x-1)
def sumPowersOfTwo(a: Int, b: Int): Int =
if(a > b) 0 else powerOfTwo(a) + sumPowersOfTwo(a+1, b)
上面的函數(shù)都是從a到b的f(n)的累加形式,我們可以抽取這些函數(shù)中共同的部分重新編寫函數(shù)sum硬贯,其中定義的f作為一個(gè)參數(shù)傳入到高階函數(shù)sum中:
def sum(f: Int => Int, a: Int, b: Int): Int =
if(a > b) 0 else f(a) + sum(f, a+1, b)
def id(x: Int): Int = x
def square(x: Int): Int = x * x
def powerOfTwo(x: Int): Int = if(x == 0) 1 else 2 * powerOfTwo(x-1)
def sumInts(a: Int, b: Int): Int = sum(id, a, b)
def sumSquared(a: Int, b: Int): Int = sum(square, a, b)
def sumPowersOfTwo(a: Int, b: Int): Int = sum(powerOfTwo, a, b)
有用的高階函數(shù)
map方法將一個(gè)函數(shù)應(yīng)用到某個(gè)集合的所有元素并返回結(jié)果焕襟;foreach將函數(shù)應(yīng)用到每個(gè)元素。
//打印三角形
scala> (1 to 9).map("^" * _).foreach(println _)
^
^^
^^^
^^^^
^^^^^
^^^^^^
^^^^^^^
^^^^^^^^
^^^^^^^^^
filter方法輸出所有匹配某個(gè)特定條件的元素:
scala> (1 to 9).filter(_ % 2 == 0)
res14: scala.collection.immutable.IndexedSeq[Int] = Vector(2, 4, 6, 8)
可以通過練習(xí)使用Scala集合庫中的一些常用的接受函數(shù)參數(shù)的方法來熟悉高階函數(shù)饭豹。
柯里化
柯里化(Currying)指的是將原來接受兩個(gè)參數(shù)的函數(shù)變成新的接受一個(gè)參數(shù)的函數(shù)的過程胧洒。新的函數(shù)返回一個(gè)以原有第二個(gè)參數(shù)為參數(shù)的函數(shù)。
返回函數(shù)的函數(shù)
在上面高階函數(shù)的例子中墨状,我們通過def sumInts(a: Int, b: Int): Int = sum(x => x, a, b)
、def sumSquared(a: Int, b: Int): Int = sum(x => x*x, a, b)
來定義新的函數(shù)菲饼,上面這兩個(gè)函數(shù)每次都要傳入a和b兩個(gè)參數(shù)到sum函數(shù)中肾砂,我們能否簡化這些參數(shù)使得函數(shù)定義更簡單呢?
我們可以通過返回函數(shù)的函數(shù)來簡化參數(shù):
def sum(f: Int => Int): (Int, Int) => Int = {
def sumF(a: Int, b: Int): Int =
if(a > b) 0
else f(a) + sumF(a+1, b)
sumF
}
//于是得到如下定義宏悦,這樣就簡化了參數(shù)
def sumInts = sum(x => x)
def sumSquared = sum(x => x * x)
def sumPowersOfTwo = sum(powerOfTwo)
多個(gè)參數(shù)列表
根據(jù)上面的例子镐确,我們能不能更加簡化包吝,省去sumInts
、sumSquared
源葫、sumPowersOfTwo
這幾個(gè)中間函數(shù)的形式呢诗越?
通過sum(square)(1, 10)
函數(shù)來替代sumSquared
函數(shù)。
一般情況息堂,這類函數(shù)的左結(jié)合的:sum(square)(1, 10) == (sum(square))(1, 10)
嚷狞。
我們可以這樣定義sum函數(shù):
def sum(f: Int => Int)(a: Int, b: Int): Int =
if(a > b) 0 else f(a) + sum(f)(a + 1, b)
這使得函數(shù)編寫更加簡潔。
一般的荣堰,多參數(shù)函數(shù)定義為def f(args1)...(argsn) = E
,
當(dāng)n > 1時(shí)床未,等同于def f(args1)...(args n-1) = {def g(argsn) = E; g}
或者def f(args1)...(args n-1) = (argsn => E)
。
如果重復(fù)這個(gè)過程n次振坚,得到def f = (args1 => (args2 => ... (argsn => E) ) )
薇搁。
這種函數(shù)定義稱為柯里化(Currying)。
轉(zhuǎn)載請(qǐng)注明作者Jason Ding及其出處
GitCafe博客主頁(http://jasonding1354.gitcafe.io/)
Github博客主頁(http://jasonding1354.github.io/)
CSDN博客(http://blog.csdn.net/jasonding1354)
簡書主頁(http://www.reibang.com/users/2bd9b48f6ea8/latest_articles)
百度搜索jasonding1354進(jìn)入我的博客主頁