函數式編程中的pointfree的意思就是「無參」或「無值」,pointfree style是一種編程範式,也做tacit programming,就是「無參編程」的意思了。什麼是「無參編程」?javascript
// 這就是有參的,由於有word var snakeCase = word => word.toLowerCase().replace(/\s+/ig, '_'); // 這是pointfree var snakeCase = compose(replace(/\s+/ig, '_'), toLowerCase);
從另外一個角度看,有參的函數的目的是獲得一個數據,而pointfree的函數的目的是獲得另外一個函數。
因此,以下的方程,雖然也有參,也能夠認爲是pointfree的。html
const titlesForYear = year => pipe( filter(publishedInYear(year)), map(book => book.title) )
那這pointfree有什麼用?
它可讓咱們把注意力集中在函數上,參數命名的麻煩確定是省了,代碼也更簡潔優雅。
須要注意的是,一個pointfree的函數多是由衆多非pointfree的函數組成的,也就是說底層的基礎函數大都是有參的,pointfree體如今用基礎函數組合而成的高級函數上。若是咱們使用函數式編程的工具,如ramda,這些基礎函數大都已經被寫好了,這樣咱們去寫pointfree的代碼就很容易了。java
什麼是聲明式編程?它區別於命令式編程git
// 命令式 var words = []; for (i = 0; i < otherWords.length; i++) { words.push(otherWords[i].word); } // 聲明式 var words = otherWords.map(function(ele){ return ele.word; });
容易看出,命令式的代碼,咱們不但要去遍歷,還要關注如何遍歷。而聲明式的就容易不少,能夠節省咱們的注意力,代碼也更加簡潔。github
其餘的命令式的寫法有:使用ifelse
進行的條件判斷,使用算數運算符進行的算數運算,使用比較運算符進行的比較運算和使用邏輯運算符進行的邏輯運算。編程
至於那些說「雖然如此,但使用命令式循環速度要快不少」的人,我建議大家先去學學 JIT 優化代碼的相關知識。這裏有一個 很是棒的視頻,可能會對你有幫助。
須要注意的是,要實現這種聲明式的編程,首先咱們要有這個map
方法,這一點與pointfree相同,都是須要咱們先對經常使用的操做作一次封裝,而這些經常使用的操做自己仍是命令式的。數組
pointfree的聲明式代碼是函數式編程應該有的樣子。ide
最後用一個來自Scott Sauyet的文章《Favoring Curry》中的例子,使用的函數式工具是ramda。下面的代碼不須要一句一句的看,大概體會一下就能夠了。函數式編程
一組JSON數據函數
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全部未完成的任務,並按照到期日期升序排列。
正確的結果是
[ {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) ); // 排除已經完成的任務 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')); // 合成函數 var getIncompleteTaskSummaries = function(membername) { return fetchData().then( R.pipe( SelectTasks, filterMember(membername), excludeCompletedTasks, selectFields, sortByDueDate, ) ); };
參考文章
我在github https://github.com/zhuanyongx...