摘要:函數(shù)式編程中的的意思就是無參或無值,是一種編程范式,也作,就是無參編程的意思了。的聲明式代碼是函數(shù)式編程應(yīng)該有的樣子。
函數(shù)式編程中的pointfree的意思就是“無參”或“無值”,pointfree style是一種編程范式,也作tacit programming,就是“無參編程”的意思了。什么是“無參編程”?
// 這就是有參的,因?yàn)橛衱ord var snakeCase = word => word.toLowerCase().replace(/s+/ig, "_"); // 這是pointfree var snakeCase = compose(replace(/s+/ig, "_"), toLowerCase);
從另一個(gè)角度看,有參的函數(shù)的目的是得到一個(gè)數(shù)據(jù),而pointfree的函數(shù)的目的是得到另一個(gè)函數(shù)。
所以,如下的方程,雖然也有參,也可以認(rèn)為是pointfree的。
const titlesForYear = year => pipe( filter(publishedInYear(year)), map(book => book.title) )
那這pointfree有什么用?
它可以讓我們把注意力集中在函數(shù)上,參數(shù)命名的麻煩肯定是省了,代碼也更簡潔優(yōu)雅。
需要注意的是,一個(gè)pointfree的函數(shù)可能是由眾多非pointfree的函數(shù)組成的,也就是說底層的基礎(chǔ)函數(shù)大都是有參的,pointfree體現(xiàn)在用基礎(chǔ)函數(shù)組合而成的高級函數(shù)上。如果我們使用函數(shù)式編程的工具,如ramda,這些基礎(chǔ)函數(shù)大都已經(jīng)被寫好了,這樣我們?nèi)憄ointfree的代碼就很容易了。
什么是聲明式編程?它區(qū)別于命令式編程
// 命令式 var words = []; for (i = 0; i < otherWords.length; i++) { words.push(otherWords[i].word); } // 聲明式 var words = otherWords.map(function(ele){ return ele.word; });
容易看出,命令式的代碼,我們不但要去遍歷,還要關(guān)注如何遍歷。而聲明式的就容易很多,可以節(jié)省我們的注意力,代碼也更加簡潔。
其他的命令式的寫法有:使用ifelse進(jìn)行的條件判斷,使用算數(shù)運(yùn)算符進(jìn)行的算數(shù)運(yùn)算,使用比較運(yùn)算符進(jìn)行的比較運(yùn)算和使用邏輯運(yùn)算符進(jìn)行的邏輯運(yùn)算。
至于那些說“雖然如此,但使用命令式循環(huán)速度要快很多”的人,我建議你們先去學(xué)學(xué) JIT 優(yōu)化代碼的相關(guān)知識。這里有一個(gè)非常棒的視頻,可能會對你有幫助。
需要注意的是,要實(shí)現(xiàn)這種聲明式的編程,首先我們要有這個(gè)map方法,這一點(diǎn)與pointfree相同,都是需要我們先對常用的操作做一次封裝,而這些常用的操作本身還是命令式的。
pointfree的聲明式代碼是函數(shù)式編程應(yīng)該有的樣子。
最后用一個(gè)來自Scott Sauyet的文章《Favoring Curry》中的例子,使用的函數(shù)式工具是ramda。下面的代碼不需要一句一句的看,大概體會一下就可以了。
一組JSON數(shù)據(jù)
var data = { result: "SUCCESS", interfaceVersion: "1.0.3", requested: "10/17/2013 15:31:20", lastUpdated: "10/16/2013 10:52:39", tasks: [ {id: 104, complete: false, priority: "high", dueDate: "2013-11-29", username: "Scott", title: "Do something", created: "9/22/2013"}, {id: 105, complete: false, priority: "medium", dueDate: "2013-11-22", username: "Lena", title: "Do something else", created: "9/22/2013"}, {id: 107, complete: true, priority: "high", dueDate: "2013-11-22", username: "Mike", title: "Fix the foo", created: "9/22/2013"}, {id: 108, complete: false, priority: "low", dueDate: "2013-11-15", username: "Punam", title: "Adjust the bar", created: "9/25/2013"}, {id: 110, complete: false, priority: "medium", dueDate: "2013-11-15", username: "Scott", title: "Rename everything", created: "10/2/2013"}, {id: 112, complete: true, priority: "high", dueDate: "2013-11-27", username: "Lena", title: "Alter all quuxes", created: "10/5/2013"} // , ... ] };
需求是找到Scott所有未完成的任務(wù),并按照到期日期升序排列。
正確的結(jié)果是
[ {id: 110, title: "Rename everything", dueDate: "2013-11-15", priority: "medium"}, {id: 104, title: "Do something", dueDate: "2013-11-29", priority: "high"} ]
命令式的代碼如下
getIncompleteTaskSummaries = function(membername) { return fetchData() .then(function(data) { return data.tasks; }) .then(function(tasks) { var results = []; for (var i = 0, len = tasks.length; i < len; i++) { if (tasks[i].username == membername) { results.push(tasks[i]); } } return results; }) .then(function(tasks) { var results = []; for (var i = 0, len = tasks.length; i < len; i++) { if (!tasks[i].complete) { results.push(tasks[i]); } } return results; }) .then(function(tasks) { var results = [], task; for (var i = 0, len = tasks.length; i < len; i++) { task = tasks[i]; results.push({ id: task.id, dueDate: task.dueDate, title: task.title, priority: task.priority }) } return results; }) .then(function(tasks) { tasks.sort(function(first, second) { var a = first.dueDate, b = second.dueDate; return a < b ? -1 : a > b ? 1 : 0; }); return tasks; }); };
pointfree的代碼
var getIncompleteTaskSummaries = function(membername) { return fetchData() .then(R.prop("tasks")) .then(R.filter(R.propEq("username", membername))) .then(R.reject(R.propEq("complete", true))) .then(R.map(R.pick(["id", "dueDate", "title", "priority"]))) .then(R.sortBy(R.prop("dueDate"))); };
pointfree的聲明式的代碼
// 提取 tasks 屬性 var SelectTasks = R.prop("tasks"); // 過濾出指定的用戶 var filterMember = member => R.filter( R.propEq("username", member) ); // 排除已經(jīng)完成的任務(wù) var excludeCompletedTasks = R.reject(R.propEq("complete", true)); // 選取指定屬性 var selectFields = R.map( R.pick(["id", "dueDate", "title", "priority"]) ); // 按照到期日期排序 var sortByDueDate = R.sortBy(R.prop("dueDate")); // 合成函數(shù) var getIncompleteTaskSummaries = function(membername) { return fetchData().then( R.pipe( SelectTasks, filterMember(membername), excludeCompletedTasks, selectFields, sortByDueDate, ) ); };
參考文章
Pointfree編程風(fēng)格指南
Favoring Curry
JS函數(shù)式編程指南
Tacit programming
Thinking in Ramda: Pointfree Style
Thinking in Ramda: Declarative Programming
我在github https://github.com/zhuanyongx...
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/94592.html
摘要:組合的概念是非常直觀的,并不是函數(shù)式編程獨(dú)有的,在我們生活中或者前端開發(fā)中處處可見。其實(shí)我們函數(shù)式編程里面的組合也是類似,函數(shù)組合就是一種將已被分解的簡單任務(wù)組織成復(fù)雜的整體過程。在函數(shù)式編程的世界中,有這樣一種很流行的編程風(fēng)格。 JavaScript函數(shù)式編程,真香之認(rèn)識函數(shù)式編程(一) 該系列文章不是針對前端新手,需要有一定的編程經(jīng)驗(yàn),而且了解 JavaScript 里面作用域,閉...
摘要:注意是單一參數(shù)柯里化是由以邏輯學(xué)家命名的,當(dāng)然編程語言也是源自他的名字,雖然柯里化是由和發(fā)明的。辨別類型和它們的含義是一項(xiàng)重要的技能,這項(xiàng)技能可以讓你在函數(shù)式編程的路上走得更遠(yuǎn)。 slide 地址 三、可以,這很函數(shù)式~ showImg(https://segmentfault.com/img/remote/1460000015978685?w=187&h=160); 3.1.函數(shù)是一...
摘要:組合組合的功能非常強(qiáng)大,也是函數(shù)式編程的一個(gè)核心概念,所謂的對過程進(jìn)行封裝很大程度上就是依賴于組合。在理解之前,先認(rèn)識一個(gè)東西概念容器容器為函數(shù)式編程里普通的變量對象函數(shù)提供了一層極其強(qiáng)大的外衣,賦予了它們一些很驚艷的特性。 前言 JavaScript是一門多范式語言,即可使用OOP(面向?qū)ο螅部梢允褂肍P(函數(shù)式),由于筆者最近在學(xué)習(xí)React相關(guān)的技術(shù)棧,想進(jìn)一步深入了解其思想...
摘要:為此決定自研一個(gè)富文本編輯器。例如當(dāng)要轉(zhuǎn)化的對象有環(huán)存在時(shí)子節(jié)點(diǎn)屬性賦值了父節(jié)點(diǎn)的引用,為了關(guān)于函數(shù)式編程的思考作者李英杰,美團(tuán)金融前端團(tuán)隊(duì)成員。只有正確使用作用域,才能使用優(yōu)秀的設(shè)計(jì)模式,幫助你規(guī)避副作用。 JavaScript 專題之惰性函數(shù) JavaScript 專題系列第十五篇,講解惰性函數(shù) 需求 我們現(xiàn)在需要寫一個(gè) foo 函數(shù),這個(gè)函數(shù)返回首次調(diào)用時(shí)的 Date 對象,注意...
摘要:期函數(shù)式編程中代碼組合如何理解定義顧名思義,在函數(shù)式編程中,就是將幾個(gè)有特點(diǎn)的函數(shù)拼湊在一起,讓它們結(jié)合,產(chǎn)生一個(gè)嶄新的函數(shù)代碼理解一個(gè)將小寫轉(zhuǎn)大寫的函數(shù)一個(gè)在字符后加的函數(shù)將兩個(gè)函數(shù)組合起來這里假設(shè)我們實(shí)現(xiàn)了每日一題每日一題顯示結(jié)果里上面 20190315期 函數(shù)式編程中代碼組合(compose)如何理解? 定義: 顧名思義,在函數(shù)式編程中,Compose就是將幾個(gè)有特點(diǎn)的函數(shù)拼湊在...
閱讀 4607·2021-09-26 09:55
閱讀 1352·2019-12-27 12:16
閱讀 879·2019-08-30 15:56
閱讀 1895·2019-08-30 14:05
閱讀 983·2019-08-30 13:05
閱讀 1261·2019-08-30 10:59
閱讀 1437·2019-08-26 16:19
閱讀 1880·2019-08-26 13:47