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书上的一大部分设计模式就没用了。条件越复杂,模式匹配就越有用。一旦你熟悉了模式匹配,就会开始奇怪:没有它的这些年你是怎么挨过来的。