为啥说函数是一等公民

论道无法目前无法用markdown语法
http://note.youdao.com/noteshare?id=7a2cfa7d7397bbd77cb6a511dcb61ce6
如果不懂递归,请先看上面的链接,并建议了解递归后再观看这篇文章 
http://note.youdao.com/noteshare?id=617c42737cbb47e6ea258ccdda3b869a​ 
可以直接访问链接# 函数是一等公民 
## 初步抽象
看下面的三个过程
 
给出两个参数 a 和 b,计算出:a到b之间的各个整数之和(包含a和b),例如: 1+2+3+4..
给出两个参数 a 和 b,计算出:a到b之间的各个整数的立方之和(包含a和b),例如: 1的立方+2的立方+3的立方
给出两个参数 a 和 b,计算出:a到b之间的各个奇数(包含a和b),与相邻的数字两两相乘为分母,1为分子的分数的和,例如: 1/(1 * 3) + 1/(5 * 7) + 1/(9 * 11)
试寻找三者的相同点,抽象出一个函数sum,这个函数接受四个参数,a,b和两个函数,使得三个过程可以共享相同的逻辑框架(第三个稍微难一点,但还是可以复用的)
### 观察
1+2+3+4..   
1的立方+2的立方+3的立方   
1/(1 * 3) + 1/(5 * 7) + 1/(9 * 11)
 
### 提出相似结构
 
1+##(2+3+4..)##   
1的立方+##(2的立方+3的立方 )##   
1/(1 * 3) + ##(1/(5 * 7) + 1/(9 * 11))##
 
```
function sum(term , start , next , end){
    if(start > end){return 0}
    //如果当前值(start一开始是开始值,但是对于每一步是当前参数)大于最后的一个数,说明累加到最后了,输出一个零代表结束
    
    //累积相当于两个部分, 第一个值  与 剩下的值
    //term(start) 是根据 当前值 获得对应的值
    //其他的不管,用递归的思想把后续扔回给同名函数
    return term(start) + sum(term, next(start) , next ,  end),
}
```
 
product函数接受四个参数a,b和两个函数。product用于计算给定范围(a到b)的某个函数值的乘积。
 
比如2~6之间每个数的3倍积
 
(2 * 3) * (3 * 3) * (4 * 3) * (5 * 3) * (6 * 3)
### 观察
(2 * 3) * (3 * 3) * (4 * 3) * (5 * 3) * (6 * 3)
 
### 提取相似结构
(2 * 3) * ###(3 * 3) * (4 * 3) * (5 * 3) * (6 * 3)###
 
```
function product(term, start , next , end){
    if(start > end){return 1}
    //乘法的结束 为 *1
    
    // 累积 前后关系 是通过 乘号来结合起来 (combiner) 的
    return term(start) * product(term , next(start) , next ,end)
}
```
## 再次抽象
 
 
sum和product都是另一种成为accumulate的特殊情况而已。现在想方法用accumulate覆盖 sum 和 product 算法
 
### 观察
```
function sum(term , start , next , end){
    if(start > end){return 0}
    return term(start) + sum(term, next(start) , next ,  end)
}
function product(term, start , next , end){
    if(start > end){return 1}
    return term(start) * product(term , next(start) , next ,end)
}
```
 
### 提出相似结构 区分 不同点
```
if(start > end){return 0}
if(start > end){return 1}
//不同点为 结束返回值 作为 一种参数 output
term(start) + sum(term, next(start) , next ,  end)
term(start) * product(term , next(start) , next ,end)
//中间的 结合方式不同 把结合方式 当作一种参数 sum 与 product 也是 accumulate的形式的一种 不断套用
 
```
现在accumulate使用的是与sum和product一样的参数项和范围描述参数,再加上一个(两个参数的)combiner函数和一个 output 参数。
 
```
function accumulate(combiner , output ,term, start , next , end  ){
    if(start > end){return output}
    return combiner( term(start) , accumulate(combiner , output , term , next(start) , next ,end))
}
 
```
 
写一个filtered-accumulate,表现更加通用的能力。过滤掉一些 值
例如
 
我们通过filter挑出1到100的偶数,然后计算sum或product。
```
function filter (x){
    if (x%2 == 0) { 
        return true;
    }
    return false;
}
```
### 分析 filter 作用在 start 上面 根据start 来判断是否进行 结合两个值 还是 放到再一次符合要求的 start 值 才结合两个值
 
```
function filtered_accumulate(filter, combiner, output, term, start, next, end) {
    if(start > end){return output}
    if(filter(start)){
         return combiner(term(start),filtered_accumulate(filter, combiner , output , term , next(start) , next , end))
    }else{
        return filtered_accumulate(filter,combiner,output,term,next(start),next,end)   
    }  
}
```
 
## 附加题 严重超纲
计算正切函数
 
tan x = x/(1 - x * x/(3 - x * x/(5 - x * x/(7 - x * x.....))))
 
其中x表示弧度,我们用tag_cf(x, k)定义这个过程
 
其中x表示弧度,k表示计算的项数。
 
这里面用到的就是所谓的连分式。
 
## 从零开始抽象
牛顿法逼近函数fun(x) = 0的一个数值解,其中x的定义域实数全部。
```
function fun(x){
    return x+x*x - 10
    //一元二次方程
}
```
```
solve(fun, x, dx)
```
solve返回result,result是正确解的近似值 其中fun为f(x)这个函数, x是输入的一个用来逼近起始点(任何实数都可以),我们可以理解他是我们认为接近正确解的值类似上面的start,
 
dx是fun(不是x的x(不断靠近))-0的误差值
这个误差值小于dx我们认为x是符合我们逼近要求的近似解。
类似上面的终止条件 start > end 
现在变成一个根据 x 与 dx 的函数
 
逼近的具体方法,伪代码如下:
 
根据牛顿微分方程 
 
dy = (fun(x+dx)-fun(x))
导数 = dy/dx
 
```
diff(x) = (fun(x+dx)-fun(x))/dx;
 
```
误差值就是 存在导数(如果导数为零就是我们的目标结果)带来的
 
我们现在要缩减误差 , 逼近后的一个值,
 
根据高中知识通过导数 与当前点做 三角形
 
函数在x点的斜率,函数x点上做切线,QQ这条切线与x轴的焦点一定在要求的值的一边并像最终结果靠近。
```
next(x) = x -  fun(x)/diff(x)
 
```
 
```
function solve(fun, x, dx){
    
    if( dx > Math.abs(fun(x))){return x}
    //先对 fun(x)去绝对值,看看是否符合我们要求的误差
    
    
    function next(x) {
        return x - fun(x)/diff(x)
    }
    //如果不符合,我们要想方法求出 向它逼急的方法
    
    function diff(x){
        return (fun(x+dx)-fun(x))/dx;
    }
    //逼近的点依赖与导数计算
    
    //把逼近点递归到同名方程/函数,不断逼近
    return solve(fun,next(x),dx)
}
```
 
## 再度抽象
写一个复合函数f(g(x))的实现,compose(f,g),其中f和g是两个函数的运算过程 他返回一个函数过程,
### 思考
如果 值返回 f(x) 是怎么的
```
    function compose(f,g){
        return function(x){
            return f(x)
        }
    }
```
然后进一步 返回 f(g(x))
```
    function compose (f, g){
        return function(x){
            return f(g(x))
        }
        
    }
```
刚才只是热身
 
现在通过微分进行迭代查找方程解的,这道题我们通过传入检验过程和逼近过程,得到返回的函数过程来解决解方程的问题。
solve_iter(check, buzz)
 
读懂不了吧
 
其实就是复合函数的一种
先要进行检查函数
然后进行逼近函数
 
```
function  solve_iter(check, buzz)
{
    return function(fun,x,dx)
    {
        if (check(fun,x,dx)){return x}
        // 检查一下是否我们要求
        //否则 逼近下一步
        else{
          var x = buzz(fun,x,dx)
           //下一个x 给好的函数 与参数求出来
           // 由于这里是要递归逼近, 就把,其他所有不变的参数,一起当作参数送出去
           //如何送出去呢,先调用一次 solver_iter 就行 
          return solve_iter(check,buzz)(fun,x,dx)
        }
      
    }
}
 
```
# 把每一步的实现方式都抽象后,整体的逻辑不变,但是每一个子方程都变得异常简单 
已邀请:

要回答问题请先登录注册