函数式编程的另类指南(10)

By | November 7, 2013

The following part is not maintained anymore. Please go to 函数式程序设计的另类指南 for the whole translation.

以下内容不再更新,浏览全部翻译,请访问 函数式程序设计的另类指南


原文链接:Functional Programming For The Rest of Us
原文作者:Vyacheslav Akhmechet

模式匹配

模式匹配不是什么新特性。事实上,它和函数式编程的关系不大。为什么总是把它当做函数式编程的一个特性呢?这是因为函数式语言已经支持模式匹配一段时间了,而现代命令式语言还不行。

用一个例子来进一步了解模式匹配。下面是Java实现的斐波那契函数:

int fib(int n) {
  if(n == 0) return 1;
  if(n == 1) return 1;

  return fib(n - 2) + fib(n - 1);
}

如果用我们上文构造的并且支持模式匹配的Java来写,实现如下

int fib(0) {
  return 1;
}

int fib(1) {
  return 1;
}

int fib(int n) {
  return fib(n - 2) + fib(n - 1);
}

两者有什么区别?编译器为我们实现了分支。

这有什么大不了的?的确没什么。有人注意到很多函数都包含非常复杂的switch语句(函数式程序中尤其如此)并且觉得这是一种很好的抽象方式。我们将函数拆分成多个,然后通过函数参数实现模式(有点象重载)。当编译器调用函数的时候,会比较传入的参数和定义中的参数,然后选择匹配的那个执行。通常来说,编译器会选择最佳匹配。比如,int fib(int n)也可以在当n为1时被匹配,但因为int fib(1)是最佳匹配,所以编译器不会选择int fib(int n)

模式匹配通常比例子中揭示的更加复杂。比如,高级模式匹配系统允许我们这样做:

int f(int n < 10) { ... }
int f(int n) { ... }

模式匹配在什么时候适用?当有一大堆case的时候!每次当你需要写一个包含嵌套if的复杂结构时,模式匹配都可以用更少的代码取得更好的效果。一个很好的例子闪现在我脑海里。这就是所有Win32平台都提供的标准WinProc函数(即使它通常被抽象了)。一般来说一个好的模式匹配系统既可以检查集合,也可以检查简单值。比如,当传给函数一个数组后,可以设计这样一个模式:当首元素为1并且第三个元素大于3的时候,该模式被匹配。

模式匹配的另一个好处就是,当你需要添加或者改变条件时,不用去检查这个庞大的函数。而只需要添加(或修改)相应的那个模式定义。这样Gof书上的一大部分设计模式就没用了。条件越复杂,模式匹配就越有用。一旦你熟悉了模式匹配,就会开始奇怪:没有它的这些年你是怎么挨过来的。

Leave a Reply

Your email address will not be published. Required fields are marked *