函数式编程

函数式编程

特点

Pure & Impure

依赖外部数据

oh-to-be-pure-again
In the impure portion, checkAge depends on the mutable variable minimum to determine the result. In other words, it depends on system state which is disappointing because it increases the cognitive load by introducing an external environment.

// Impure
let minimum = 21;
let checkAge = function(age) {
  return age >= minimum;
};
// Pure
let checkAge = function(age) {
  let minimum = 21;
  return age >= minimum;
};

修改传入的变量

function squareAll(items) {
    return items.map(square);
}

//Pure functions
function square(x) {
    return x * x;
}

//Impure functions
function squareAll(items) {
    for (let i = 0; i < items.length; i++) {
        item[i] = square(items[i]);//It modified the incoming data;
    }
}

slice & splice

mostly-adequate-guide
In functional programming, we dislike unwieldy functions like splice that mutate data.

let xs = [1, 2, 3, 4, 5];
// Impure
xs.splice(0, 3);
//=> [1,2,3]

xs.splice(0, 3);
//=> [4,5]

xs.splice(0, 3);
//=> []

// Pure
xs.slice(0, 3);
//=> [1,2,3]

xs.slice(0, 3);
//=> [1,2,3]

xs.slice(0, 3);
//=> [1,2,3]

Immutable & Mutable

//Mutable
function addOne(numArray: any[]): any[] {
    for (let x in numArray) {
        numArray[x] = numArray[x] + 1;
    }
    return numArray;
}

function addOne(numArray: any[]): any[] {
    let addedArray: any[];
    for (let x in numArray) {
        addedArray[x] = numArray[x] + 1;
    }
    return addedArray;
}

function addOne(numArray: any[]): any[] {
    let addedArray: any[] = new Array();
    for (let x of numArray) {
        addedArray.push(x + 1);
    }
    return addedArray;
}

function addOne(numArray: any[]): any[] {
    let addedArray: any[];
    numArray.forEach((element, index) => {
        addedArray[index] = element + 1;
    });
    return addedArray;
}
//Immutable
function addOne(numArray: any[]): any[] {
    return numArray.map((item) => {
        return item + 1;
    })
}
let a = [1, 2, 3, 4, 5];
Object.freeze(a);
console.log(addOne(a));

foreach & map的不同?

for…in
for…of
foreach
map

foreach

函数式编程中的循环

//for loop
function accumulate(n) {
    let result = 0;
    for (n; n > 0; n--) {
        result = n + result;
    }
    return result;
}
//Recursive loop
function accumulate(n) {
    if (n === 0) {
        return 0;
    } else {
        return n + accumulate(n - 1);
    }
}

尾调用优化

//Recursive loop
function accumulate(n) {
    if (n === 0) {
        return 0;
    } else {
        return n + accumulate(n - 1);
    }
}
//Tail Call Optimization
"use strict";
function accumulate(n, result) {
    if (n === 0) {
        return result;
    } else {
        return accumulate(n - 1, n + result);
    }
}

尾调用优化
栈

为什么尾调用优化失败?

http://web.jobbole.com/86086/

一等公民 —— 函数

const hi = function (name) {
    return "Hi " + name;
};

const greeting = function (name) {
    return hi(name);
};
hi;
// function(name){
//  return "Hi " + name
// }

hi("jonas");
// "Hi jonas"
const greeting = hi;
greeting("jonas");
// "Hi jonas"
const ajaxCall = function (callback) {
    const json = {
        a: "123"
    }//do something
    return callback(json);
}
const getServerStuff = function (callback) {
    return ajaxCall(function (json) {
        return callback(json);
    });
};

const getServerStuff = ajaxCall;
return ajaxCall(function(json){
  return callback(json);
});

return ajaxCall(callback);
const getServerStuff = function(callback){
  return ajaxCall(callback);
};

const getServerStuff = ajaxCall;

函数与数学

函数式编程入门教程——阮一峰

函数的合成与柯里化

函数的合成
函数合成需要满足结合律

compose(f, compose(g, h))
compose(compose(f, g), h)
compose(f, g, h)

其他示例

找到用户 Scott 的所有未完成任务,并按到期日期升序排列

const 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"
        }
    ]
};

const fetchData = function () {
    return Promise.resolve(data);
};

let getIncompleteTaskSummaries = function (membername) {
    return fetchData()
        .then(function (data) {
            return data.tasks;
        })
        .then(function (tasks) {
            let results = [];
            for (let i = 0, len = tasks.length; i < len; i++) {
                if (tasks[i].username == membername) {
                    results.push(tasks[i]);
                }
            }
            return results;
        })
        .then(function (tasks) {
            tasks.sort(function (first, second) {
                let a = first.dueDate, b = second.dueDate;
                return a < b ? -1 : a > b ? 1 : 0;
            });
            return tasks;
        });
};

getIncompleteTaskSummaries("Scott").then((tasks) => {
    console.log(tasks)
})
let R = require('ramda');
let 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"
        }
    ]
};

let fetchData = function () {
    return Promise.resolve(data);
};

let 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.sortBy(R.prop('dueDate')));
};

getIncompleteTaskSummaries('Scott').then(r => console.log(r)); 

下面有一段字符串,请问其中最长的单词有多少个字符?


const R = require('ramda');
const str = 'Lorem ipsum dolor sit amet consectetur adipiscing elit';
// 以空格分割单词
const splitBySpace = s => s.split(' ');

// 每个单词的长度
const getLength = w => w.length;

// 词的数组转换成长度的数组
const getLengthArr = arr => R.map(getLength, arr);

// 返回较大的数字
const getBiggerNumber = (a, b) => a > b ? a : b;

// 返回最大的一个数字
const findBiggestNumber =
    arr => R.reduce(getBiggerNumber, 0, arr);
 const getLongestWordLength = R.pipe(
     splitBySpace,
     getLengthArr,
     findBiggestNumber
 );


// 上面代码的另一种写法
const getLongestWordLength = R.pipe(
    R.split(' '),
    R.map(R.length),
    R.reduce(R.max, 0)
);

console.log(getLongestWordLength(str)) // 11

你可能感兴趣的:(函数式编程)