|
牢記:函數(shù)式編程不是用函數(shù)來編程!!!
23.4函數(shù)式編程
23.4.1 什么是函數(shù)式編程
什么是函數(shù)式編程?如果你這么直白地詢問,會發(fā)現(xiàn)它竟是一個不太容易解釋的概念。許多在程序設(shè)計領(lǐng)域有著多年經(jīng)驗的老手,也無法很明白地說清楚函數(shù)式編程到底在研究些什么。函數(shù)式編程對于熟悉過程式程序設(shè)計的程序員來說的確是一個陌生的領(lǐng)域,閉包(closure),延續(xù)(continuation),和柯里化(currying)這些概念看起來是這么的陌生,同我們熟悉的if、else、while沒有任何的相似之處。盡管函數(shù)式編程有著過程式無法比擬的優(yōu)美的數(shù)學(xué)原型,但它又是那么的高深莫測,似乎只有拿著博士學(xué)位的人才玩得轉(zhuǎn)它。
提示:這一節(jié)有點難,但它并不是掌握JavaScript所必需的技能,如果你不想用JavaScript來完成那些用Lisp來完成活兒,或者不想學(xué)函數(shù)式編程這種深奧的技巧,你完全可以跳過它們,進入下一章的旅程。
那么回到這個問題,什么是函數(shù)式編程?答案很長……
函數(shù)式編程第一定律:函數(shù)是第一型。
這句話本身該如何理解?什么才是真正的第一型?我們看下面的數(shù)學(xué)概念:
二元方程式 F(x, y) = 0,x, y 是變量, 把它寫成 y = f(x), x是參數(shù),y是返回值,f是由x到y(tǒng)的映射關(guān)系,被稱為函數(shù)。如果又有,G(x, y, z) = 0,或者記為 z = g(x, y),g是x、y到z的映射關(guān)系,也是函數(shù)。如果g的參數(shù)x, y又滿足前面的關(guān)系y = f(x), 那么得到z = g(x, y) = g(x, f(x)),這里有兩重含義,一是f(x)是x上的函數(shù),又是函數(shù)g的參數(shù),二是g是一個比f更高階的函數(shù)。
這樣我們就用z = g(x, f(x)) 來表示方程F(x, y) = 0和G(x, y, z) = 0的關(guān)聯(lián)解,它是一個迭代的函數(shù)。我們也可以用另一種形式來表示g,記z = g(x, y, f),這樣我們將函數(shù)g一般化為一個高階函數(shù)。同前面相比,后面這種表示方式的好處是,它是一種更加泛化的模型,例如T(x,y) = 0和G(x,y,z) = 0的關(guān)聯(lián)解,我們也可以用同樣的形式來表示(只要令f=t)。在這種支持把問題的解轉(zhuǎn)換成高階函數(shù)迭代的語言體系中,函數(shù)就被稱為“第一型”。
JavaScript中的函數(shù)顯然是“第一型”。下面就是一個典型的例子:
Array.prototype.each = function(closure)
{
return this.length ? [closure(this[0])].concat(this.slice(1).each(closure)) : [];
}
這真是個神奇的魔法代碼,它充分發(fā)揮了函數(shù)式的魅力,在整個代碼中只有函數(shù)(function)和符號(Symbol)。它形式簡潔并且威力無窮。
[1,2,3,4].each(function(x){return x * 2})得到[2,4,6,8],而[1,2,3,4].each(function(x){return x-1})得到[0,1,2,3]。
函數(shù)式和面向?qū)ο蟮谋举|(zhì)都是“道法自然”。如果說,面向?qū)ο笫且环N真實世界的模擬的話,那么函數(shù)式就是數(shù)學(xué)世界的模擬,從某種意義上說,它的抽象程度比面向?qū)ο蟾撸驗閿?shù)學(xué)系統(tǒng)本來就具有自然界所無法比擬的抽象性。
函數(shù)式編程第二定律:閉包是函數(shù)式編程的摯友。
閉包,在前面的章節(jié)中我們已經(jīng)解釋過了,它對于函數(shù)式編程非常重要。它最大的特點是不需要通過傳遞變量(符號)的方式就可以從內(nèi)層直接訪問外層的環(huán)境,這為多重嵌套下的函數(shù)式程序帶來了極大的便利性,下面是一個例子:
(function outerFun(x)
{
return function innerFun(y)
{
return x * y;
}
})(2)(3);
函數(shù)式編程第三定律:函數(shù)可以被科里化(Currying)。
什么是Currying? 它是一個有趣的概念。還是從數(shù)學(xué)開始:我們說,考慮一個三維空間方程 F(x, y, z) = 0,如果我們限定z = 0,于是得到 F(x, y, 0) = 0 記為 F'(x, y)。這里F'顯然是一個新的方程式,它代表三維空間曲線F(x, y, z)在z = 0平面上的兩維投影。記y = f(x, z), 令z = 0, 得到 y = f(x, 0),記為 y = f'(x), 我們說函數(shù)f'是f的一個Currying解。
下面給出了JavaScript的Currying的例子:
function add(x, y)
{
if(x!=null && y!=null) return x + y;
else if(x!=null && y==null) return function(y)
{
return x + y;
}
else if(x==null && y!=null) return function(x)
{
return x + y;
}
}
var a = add(3, 4);
var b = add(2);
var c = b(10);
上面的例子中,b=add(2)得到的是一個add()的Currying函數(shù),它是當(dāng)x = 2時,關(guān)于參數(shù)y的函數(shù),注意到上面也用到了閉包的特性。
有趣的是,我們可以給任意函數(shù)一般化Currying,例如:
function Foo(x, y, z, w)
{
var args = arguments;
if(Foo.length < args.length)
return function()
{
return
args.callee.apply(Array.apply([], args).concat(Array.apply([], arguments)));
}
else
return x + y 主站蜘蛛池模板: 丰满大屁俄罗斯肥女 | 亚洲最大在线视频 | 97在线精品视频免费 | 久久香蕉国产线看观看 | 国产欧美日韩中文视频在线 | 国产人妻系列无码专区97SS | 萝莉御姐被吸奶 | 最近中文字幕MV高清在线 | 国产偷国产偷亚州清高 | 国产欧美日韩网站 | 被老头下药玩好爽 | 天美传媒在线完整免费观看网站 | 扒开美女的内衣亲吻漫画 | 亚洲人成电影网站 | 男人的天堂黄色片 | 青青久在线| 亚洲精品中文字幕制 | 国产成人精品电影 | 午夜福利小视频400 午夜福利网国产A | 国产嫩草在线观看 | 抽插内射高潮呻吟爆乳 | 国产亚洲精品视频亚洲香蕉视 | 亚洲2017天堂色无码 | 久久久国产精品免费A片蜜芽广 | 国产午夜永久福利视频在线观看 | 国产在线观看的 | 91天堂国产在线 在线播放 | 日本69色视频在线观看 | WWW国产亚洲精品久久久日本 | 亚洲精品无码久久久久A片空 | 精品一品国产午夜福利视频 | 久久国内精品视频 | 精品精品国产自在现拍 | 黑人特黄AA完整性大片 | 久久青草在线视频精品 | 美女张开腿让我了一夜 | 午夜A级理论片左线播放 | 亚洲国产AV无码综合在线 | 色就色综合 | 爽死你个放荡粗暴小淫货漫画 | 中文字幕精品无码一区二区 |