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