javascript(函数式编程思考) ---> Map-Filter-quicksort-Collatz序列-Flodl-Flodr
let add = x=>x+1; //Map :: ( a -> b) -> [a] -> [b] let Map = function(f,arr){ //闭包存储累积对象 let result = []; return function map(f,arr){ if(!Array.isArray(arr)){ return "要处理的对象为数组"; } if(arr.length ==0){ return []; }else{ let [head,...tail] = arr; result.push(f(head)); // 通过回调map遍历目标对象arr,f处理过的元素存入result,tail为[]即遍历结束,可以返回result return tail.length == 0 ? result : map(f,tail); } }(f,arr); }; let test = Map(add,[1,2,3]); console.log(test);//[2,3,4]
let biggerTen = x => x>10; //Filter :: (a -> Bool) -> [a] -> [a] let Filter = function(f,arr){ let result=[]; return function filter(f,arr){ if(!Array.isArray(arr)){ return "要处理的对象为数组"; } if(arr.length == 0){ return []; }else{ let [head,...tail] = arr; if(f(head)){ result.push(head) } return tail.length == 0 ? result : filter(f,tail); } }(f,arr); }; let testFilter = Filter(biggerTen,[1,5,10,44,12,2,5]); console.log(testFilter);//[44,12]
快速排序:
let small = x=>y=>y <=x; let bigger = x=>y=>y > x; console.log(Filter(bigger(5),[7,2,1,4])); console.log(Filter(small(5),[7,2,1,4])); //QuickSort :: (Ord a) => [a] -> [a] let QuickSort = (function(){ return function quickSort(arr){ if(arr.length == 0){ return []; }else{ let [head,...tail] = arr; let smallerSorted = quickSort(Filter(small(head),tail)); let biggerSorted = quickSort(Filter(bigger(head),tail)); return smallerSorted.concat([head]).concat(biggerSorted); } }; })(); let testQuickSort = QuickSort([5,7,2,1,4]); console.log(testQuickSort);//[1,2,4,5,7]
Collatz序列:
let div2 = x=>x/2; let someF = x=>x*3+1; const Chain = function(n){ let result=[]; return function chain(n){ result.push(n); if(n == 1){return [1]} let even = n%2 ==0 ? chain( div2(n) ) : []; let odd = n%2 !=0 ? chain( someF(n)) : []; return result; }(n); }; console.log(Chain(10));//[10,5,16,8,4,2,1]
Foldl:
// 左折叠 const Foldl = function(f,list,initValue){ if(list.length == 0){ return initValue || null; }else{ let accumulated=initValue || list.shift() ; let foldl = function(acc,x){ accumulated = f(acc,x); return list.length==0 ? accumulated : foldl(accumulated,list.shift()); } return list.length==0 ? accumulated : foldl(accumulated,list.shift()); } } let reducer = (x,y) => (x+y); let reducerMultiply = (x,y) => x*y; console.log(Foldl(reducer,[1,2,3]));//6 console.log(Foldl(reducerMultiply,[2,3,4]));//24
Foldr:
// 右折叠 const Foldr = function(f,list,initValue){ if(list.length == 0){ return initValue || null; }else { let accumulated = initValue || list.pop(); let foldr = function(x,acc){ accumulated = f(x,acc); return list.length==0 ? accumulated : foldr(list.pop(),accumulated); } return list.length==0 ? accumulated : foldr(list.pop(),accumulated); } } let reverse = (x,y) => { y.push(x); return y; }; console.log(Foldr(reverse,[1,2,3],[]));//[3,2,1]
用Fold重新创建新的Map和Filter:
// 用Foldr创建新的Filter 当然也可以用Foldl const newFilter = function(f,list){ let condition = function(x,acc){ f(x) && acc.push(x); return acc; } let result = Foldr(condition,list,[]); return Foldr(reverse,result,[]); } let bigger20 = x=>x>20; console.log(newFilter(bigger20,[10,22,50,1,41,2])); // [22,50,41] // 用Foldl 创建新的Map const newMap = function(f,list){ let map = function(acc,x){ acc.push(f(x)); return acc; } return Foldl(map,list,[]); } let addTwo = x => x+2; console.log(newMap(addTwo,[1,2,3]));//[3,4,5]