摘要:返回一個函數(shù)作為結(jié)果。利用函數(shù)將值的集合合并成一個值,該函數(shù)接受一個累積和本次處理的值。集合中心編程函數(shù)式編程對于需要操作集合中元素的任務非常有用。
函數(shù)是一等公民本文章記錄本人在學習 函數(shù)式 中理解到的一些東西,加深記憶和并且整理記錄下來,方便之后的復習。
"一等"這個術語通常用來描述值。當函數(shù)被看作“一等公民”時,那它就可以去任何值可以去的地方,很少有限制。比如那數(shù)值和函數(shù)做比較。
函數(shù)與數(shù)字一樣可以存儲為變量
var fortytwo = function () { return 42; };
函數(shù)與數(shù)字一樣可以存儲為數(shù)組的一個元素。
var fortytwos = [42, function () { return 42; }];
函數(shù)與數(shù)字一樣可以作為對象的成員變量。
var fortytows = {number: 42, fun: function () {}}
函數(shù)與數(shù)字一樣可以在使用的時候直接創(chuàng)建出來。
42 + (function () { return 42; })();
函數(shù)與數(shù)字一樣可以被傳遞給另一個函數(shù)。
function weirdAdd(n, f) { return n + f() }; weirdAdd(42, function() { return 42; });
函數(shù)與數(shù)字一樣可以被另一個函數(shù)返回。
return 42; return function() { return 42; };
關于最后兩點,其實就是對“高階”函數(shù)的定義,也就是:
以一個函數(shù)作為參數(shù)。
返回一個函數(shù)作為結(jié)果。
從上面舉的栗子可以看來。做為“一等公民”的函數(shù)就會擁有類型數(shù)字的性質(zhì)。
Applicative 編程簡單來說Applicative編程定義為函數(shù)A作為參數(shù)提供給函數(shù)B。在Applicative編程三個典型的例子是:mao、reduce和filter。
看下面栗子:
var nums = [1, 2, 3, 4, 5]; // 數(shù)組的所有項都 * 2 function doubleAll(array) { return _.map(array, function (n) { return * 2 }); } // 數(shù)組的所有項相加,返回 sum / _.size(array) function average(array) { var sum = _.reduce(array, function (a, b) { return a + b }); return sum / _.size(array); } // 塞選數(shù)組中的偶數(shù)項,并且返回一個新的數(shù)組 function onlyEven(array) { return _.filter(arr, function (n) { return (n % 2) === 0; }); } doubleAll(nums); // [2, 4, 6, 8, 10]; average(nums); // 3 only(nums); / [2,4]
看了上面的栗子,能看出mao、reduce和filter會在某一個地方最終調(diào)用作為參數(shù)的匿名函數(shù)。實際上,這些函數(shù)的語義可以由這個調(diào)用關系來定義:
_.map()遍歷集合并對每一個值調(diào)用一個函數(shù),返回結(jié)果的集合。
_.reduce利用函數(shù)將值的集合合并成一個值,該函數(shù)接受一個累積和本次處理的值。
_.filter對集合每一個值調(diào)用一個謂詞函數(shù)(也就是返回true或者false的函數(shù)),抽取謂詞函數(shù)返回true的值的集合。
集合中心編程函數(shù)式編程對于需要操作集合中元素的任務非常有用。新建一個簡單的對象:{a: 1, b: 2},然后拿_.map()使用_.identity()函數(shù)(返回其參數(shù)的函數(shù))。例如:
_.map({a: 1, b: 2}, _.identity); // [1, 2];
從集合為中心的角度看,Underscore和一般函數(shù)式編程所提倡的是要建立一個統(tǒng)一的處理方式,使我們可以重用一套綜合的函數(shù)。
定義幾個 Applicative 函數(shù)用 100 個函數(shù)操作一個數(shù)據(jù)結(jié)構(gòu),必用 10 個函數(shù)操作 10 個數(shù)據(jù)結(jié)構(gòu)要好。
Underscore提供了許多的applicative函數(shù),有興趣的可以去閱讀一下API以及源碼。通過小栗子來看看如何創(chuàng)建一個applicative函數(shù):
// 一個簡單、接受一定數(shù)量的參數(shù)并連接它們的函數(shù)并不是 applicative。 function cat() { var head = _.frist(arguments); if (existy(head)) return head.concat.apply(head, _.reset(arguments)); else return []; } cat([1, 2, 3], [4, 5], [6, 7, 8]); // [1, 2, 3, 4, 5, 6, 7, 8]
接著繼續(xù)定義一個construct函數(shù),construct函數(shù)接受一個元素和一個數(shù)組,并且cat將元素防止在數(shù)組前方:
function construct(head, tail) { return cat([head], _.toArray(tail))); } construct(42, [1, 2, 3]); // [42, 1, 2, 3]
雖然上面的construct函數(shù)中使用到了cat,但是它并沒有將cat作為參數(shù)傳入,所以不符合要求。
在定義一個函數(shù)mapcat:
function mapcat(fun, coll) { return cat.apply(null, _.map(coll, fun); } mapcat(function (e) { return construct(e, [","]); }, [1,2,3]); // [1, ",", 2, ",", 3, ","]
mapcat函數(shù)接受一個函數(shù)fun,與_.map用了相同的方式,對給定集合中的每個元素進行調(diào)用。這種fun的使用是mapcat的applicative本質(zhì)。
當映射函數(shù)返回一個數(shù)組,mapcat可以將其展平。接著繼續(xù)定義butLast和interpose函數(shù):
function butLast(coll) { return _.toArray(coll).slice(0, -1); } function interpose(inter, coll) { return butLast(mapcat(function (e) { return construct(e, [inter]); }, coll)); } interpose(",", [1, 2, 3]); // [1, ",", 2, ",", 3]
數(shù)據(jù)思考用較低級別的函數(shù)來逐步定義和使用離散功能。
在js中,對象類型是非常強大的,但與其一起工作的工具并不完全是函數(shù)式的。相反,用js對象更常用的模式是,以多態(tài)調(diào)度為目的來附加方法。
雖然把js對象當成數(shù)據(jù)映射來操作和訪問的工具本身很少,但是幸好有Underscore提供了有用的一系列操作。其中有:_.keys,_.values和_.pluck。有興趣的可以去看看API文檔。
拿_.pluck函數(shù)和_.omit函數(shù)做一個小栗子:
var person = {name: "Romy", token: "j3983ij", password: "trigress"}; var info = _.omit(person, "token", "password"); // {name: "Romy"} var creds = _.pick(person, "token", "password"); // {token: "j3983ij", password: "trigress"}
上面的栗子是,使用相同的“危險”鍵:token和password,_.onmit函數(shù)接受一個黑名單,從對象中刪除鍵,而_.pick根據(jù)白名單保留相應鍵,且都不會修改原來的對象。
如果使用過了Underscore函數(shù)來操作對象,你會覺得非常類似與SQL,都是根據(jù)一個強大的聲明規(guī)約進行過濾和處理邏輯數(shù)據(jù)表。
總結(jié)最后總結(jié)一下一等函數(shù):
它們可以存儲在變量中。
它們可以被存儲在數(shù)組中的插槽中。
它們可以存儲在對象的字段中。
它們可以根據(jù)需求來創(chuàng)建。
它們可以被傳遞到其他函數(shù)中。
它們可以被其他函數(shù)返回。
一等函數(shù)的意思就是以上的幾點了。可以簡單它擁有數(shù)值一樣的性質(zhì)。
在總結(jié)一下applicative編程,簡單來說就是函數(shù)A作為參數(shù)提供給函數(shù)B。_.map、_.reduce和_.filter就是最好的例子。
有啥不對,請斧正!
文章版權歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/85874.html
摘要:不純的函數(shù)充滿的不確定性,在函數(shù)式編程中要盡量避免它。在以后的函數(shù)式編程中還會不斷的遇見它的。 一.為什么需要柯里化(curry函數(shù)) 1.先簡單的介紹一下純函數(shù) 在函數(shù)式編程中純函數(shù)是其最基本的思想,所謂純函數(shù)就是一個相對不受外界影響(之所以說相對,是因為有的時候需要和外界溝通,函數(shù)沒法保持所謂真正的純,但后面會有方法來解決).在高中數(shù)學中都學過,函數(shù)是一種映射關系,在y=f(x)這...
摘要:在近期看到了函數(shù)式編程這本書預售的時候就定了下來。主要目的是個人目前還是不理解什么是函數(shù)式編程。且和現(xiàn)在在學習函數(shù)式編程有莫大的關系。加速大概了解了函數(shù)式編程之后??偨Y(jié)看完了第一章也是可以小結(jié)一下的函數(shù)式編程。 本文章記錄本人在學習 函數(shù)式 中理解到的一些東西,加深記憶和并且整理記錄下來,方便之后的復習。 在近期看到了《JavaScript函數(shù)式編程》這本書預售的時候就定了下...
摘要:設定瀏覽器屬性的屬性的方法叫做駝峰式命名是函數(shù)名方法名和對象屬性名的命名首選格式。由瀏覽器預先定義的對象被稱為宿主對象。在給某個元素添加了事件處理函數(shù)后,一旦事件發(fā)生,相應的代碼就會執(zhí)行。 1.JavaScript是一個使網(wǎng)頁具有交互能力的程序設計語言。 2.設定瀏覽器屬性的屬性的方法叫做BOM. 3.駝峰式命名(myMood)是函數(shù)名、方法名和對象屬性名的命名首選格式。 4.命名變量...
摘要:但是,最好使用差異化的類型定義,函數(shù)簽名如下其實二者說的是同一件事。后者的返回值和初始函數(shù)的返回值相同,即。破壞式更新和函數(shù)式更新的比較三的延遲計算的設計者們在將引入時采取了比較特殊的方式。四匹配模式語言中暫時并未提供這一特性,略。 一、無處不在的函數(shù) 一等函數(shù):能夠像普通變量一樣使用的函數(shù)稱為一等函數(shù)(first-class function)通過::操作符,你可以創(chuàng)建一個方法引用,...
摘要:當我們希望能界定這二者之間的區(qū)別時,我們將第一種稱為純粹的函數(shù)式編程,后者稱為函數(shù)式編程。函數(shù)式編程我們的準則是,被稱為函數(shù)式的函數(shù)或方法都只能修改本地變量。另一種觀點支持引用透明的函數(shù)式編程,認為方法不應該有對外部可見的對象修改。 一、實現(xiàn)和維護系統(tǒng) 1.共享的可變數(shù)據(jù) 如果一個方法既不修改它內(nèi)嵌類的狀態(tài),也不修改其他對象的狀態(tài),使用return返回所有的計算結(jié)果,那么我們稱其為純粹...
閱讀 2566·2023-04-26 01:44
閱讀 2577·2021-09-10 10:50
閱讀 1420·2019-08-30 15:56
閱讀 2286·2019-08-30 15:44
閱讀 525·2019-08-29 11:14
閱讀 3429·2019-08-26 11:56
閱讀 3025·2019-08-26 11:52
閱讀 921·2019-08-26 10:27