高阶函数之函数作为参数

来源:互联网 发布:知乎电子书 参与 编辑:程序博客网 时间:2024/04/29 20:11

SICP 1.3.1  Procedures as Arguments,说明高阶函数之函数作为参数的原因:若干个函数拥有相似的算法或代码结构,对此加以抽象

(define (sum-integers a b)  (if (> a b)      0      (+ a (sum-integers (+ a 1) b))))(define (pi-sum a b)  (if (> a b)      0      (+ (/ 1.0 (* a (+ a 2))) (pi-sum (+ a 4) b))))

于是:

清单1:
(define (sum term a next b)  (if (> a b)      0      (+ (term a)         (sum term (next a) next b))))
这里使用Java完成相同的工作。核心知识:3.3模板方法模式2

话说这里有3个求和函数/方法,按照SICP 1.3.1的命名sum_integers求代数和,sum_cubes求立方数的代数和,pi求1/(1*3)+1/(5*7)+1/(9*11)+...的某些项的和(不要管递归和迭代、int与double),总之,下面的代码难看,yqj2065将它们搞成static方法。

package higherOrderFunction;/** * * @author yqj2065 */public class SomeSum {    public static double identity (int x){        return x;    }    public static double sum_integers(int a,int b){        int sum=0;        for(int i =a;i<=b;i++){            sum+=identity(i);        }        return sum;            }    public static double cube(int x){        return x*x*x;    }    public static int sum_cubes(int a,int b){        int sum=0;        for(int i =a;i<=b;i++){            sum+=cube(i);        }        return sum;            }    /**     * the sum of a sequence of terms in the series 1/(1*3)+1/(5*7)+1/(9*11)+...     */    public static double item(int x){        return 1.0/(x*(x+2));    }    public static double pi(int a,int b){        double sum=0;        for(int i =a;i<=b;i+=4){            sum+=item(i);        }        return sum;            }    public static void main(String[] a){        System.out.println(sum_cubes(1,10));        System.out.println(sum_integers(1,10));        System.out.println("pi="+8*pi(1,1000));    }    }
不管是那种语言,看着这样的代码就要抽象一下。Scheme使用高阶函数——函数作为参数型

Java 8前,比较笨拙些。Sum类是一个模板类,getSum(int a,int b)是模板方法,而next和item就是大名鼎鼎的钩子。NextInterface, ItemInterface在你不愿意使用Java的λ表达式时可以不要,它们是函数接口(代码略)。

package higherOrderFunction;public class Sum implements NextInterface, ItemInterface {    public final double getSum(int a,int b){        double sum=0;        for(int i =a;i<=b; i=next(i)){            sum+=item(i);        }        return sum;            }    @Override    public int next(int i) {return 0;}    @Override    public double item(int x){return 0;}}

这个代码比较清单1,是要多几行代码。现在实现Sum_pi,pi求和。main方法你可以放在Test类中,它还实现了sum_integers

package higherOrderFunction;public class Sum_pi extends Sum {    @Override  public double item(int x) {        return 1.0 / (x * (x + 2));    }    @Override    public int next(int i) {        return i + 4;    }    public static void main(String[] a) {        System.out.println("pi=" + 8 * new Sum_pi().getSum(1, 1000));        System.out.println("sum_integers(1,10)=" + new Sum() {            @Override public double item(int x) {                return x;            }            @Override            public int next(int i) {                return ++i;            }        }.getSum(1, 10));   }}
使用Java的λ表达式,我们按照清单1,也定义模板类Sum的4个参数的是模板方法,Java中方法,再怎么样玩花招,必须属于某个类型,即使想尽一切办法简化。所以,参数是函数接口,而非函数。

    public final double getSum(int a,int b,NextInterface iNext,ItemInterface iItem){        double sum=0;        for(int i =a;i<=b; i=iNext.next(i)){            sum+=iItem.item(i);        }        return sum;            }
而应用就简洁了:

System.out.println("sum_cube(1,10)="                + new Sum().getSum(1, 10,(i)-> {return ++i;},(x)->{ return x*x*x;})        );

pi=3.139592655589782
sum_integers(1,10)=55.0
sum_cube(1,10)=3025.0

函数式编程中,高阶函数使得模板方法模式没有存在的必要。


0 0
原创粉丝点击