0%

一起学习魔法吧(番外篇0)

任何非常先进的技术,初看都与魔法无异。

高阶函数

高阶函数是什么?在第一次遇见这个名词的时候,我还以为是封装好的轮子,只是可以实现的功能比较强大,然而其实际的含义可以解释为\

  • 接受一个或多个函数作为输入
  • 输出一个函数

    满足上述两个条件之一便可称之为高阶函数

例如我们要构建一个数学上的 Σ 符号(求和符号),可能有人觉得这有什么难的?然后给出下面这种代码

1
2
3
4
5
6
7
8
int a[10000];
int sum(int n,int *a){
   int result;
   for(int i = 0;i<n;i++){
       result += a[i];
   }
   return result;
}

这个函数却可以做到求和,但是如果我现在想求 n^2 的和怎么办呢?

1
2
3
4
5
6
7
8
int a[10000];
int sum(int n,int *a){
   int result;
   for(int i = 0;i<n;i++){
       result += pow(a[i],2);
   }
   return result;
}

好吧,但是我又想求 n^3 的和怎么办呢?就你事多

突然你的同事过来告诉你:“好吧,技术部门搞错了,他们其实想要的是平方和”

这个时候你可能已经打算举起手中键盘了,但是等等,你不觉得这样写求和函数代码根本没有复用性吗?如果我的求和函数又要更改步长怎么办?如果需求再次变动怎么办?当代码比较少的时候你可能还能找到令你抓狂的求和函数并修改它,一旦程序的复杂性增长,你每次变动程序都有可能带来灾难性的后果。这个时候你可能会想到面向对象编程(oop),但是我们今天不讨论这个,我们试图用高阶函数来解决这个问题。 作者:菌汤锅好吃

额,这个看上去够丑的,那些个函数指针是什么?我们为什么要构建这么丑的一个函数?这个函数(过程)已经很好的抽象出了数学符号 ∑ start 与 end 分别代表了上下界,next,term 两个函数(过程)分别表达了步长和操作,这样一来每次需求变化时我只要改动 sum 的参数就行了,根本不用再次修改底层的 sum 代码。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#include<stdio.h>
int next(int i) {
   //下一个迭代;
   i += 1;
   return i;
}
int square(int n) {
   n = n * n;
   return n;
}
int next2(int i) {
   i += 2;
   return i;
}
int term2(int n) {
   n = n * 2;
   return n;
}
double sum(int start, int end, int(*next)(int a), int(*term)(int b)) {
   static int result = 0;
   if (start <= end) {
       result += term(start);
       return sum(next(start), end, (*next), (*term));
   }
   else
       return result;
}
int main(){
   int a, b;
   scanf("%d %d", &a, &b);
   printf("%f",sum(a, b, next2, term2));
   printf("%f",sum(a, b ,next1, term1));
   return 0;
}