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

By | September 9, 2013

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

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


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

函数式编程

函数式程序设计是对阿隆左·丘奇思想的一种实现。但并非所有的lambda演算都被实现了,因为lambda演算原本不是为有物理限制的计算机设计的。因此,函数式像面向对象程序设计一样,只是一系列理念,而不是严格的使用手册。如今有很多种函数式编程语言,它们各自采用了不同的方法。在本文中,我将使用Java来编写函数式程序,并且解释函数式语言的常用特性(的确,如果你有受虐倾向,你可以用Java写函数式程序)。在下面几章中,我将会对Java稍作修改,以使其成为一个可用的函数式编程语言。那我们开始吧。

lambda演算被设计用来解决计算问题,所以函数式编程主要用于处理计算。正如它的名字那样,程序用函数来完成所有操作。函数是函数式程序设计的基本单位。它几乎无处不在。即使最简单的计算也由函数构成。甚至变量(variable)都由函数取代。在函数式编程中,变量只是表达式的别名(这样我们就不必把所有东西打在一行里)。变量是不能被更改的并且只能被赋值一次。在Java中,这意味着所有变量都要被声明为final(或 C++ 中的 const)。在函数式编程中没有非final的变量。

final int i = 5; 
final int j = i + 3;

因为函数式编程中的所有变量都是final的,所以可以提出这样两个有趣的假设:(1)没有必要总是写出关键字final,(2)没有必要再把变量称为变量。那么现在我们对Java作出两个修改:(1)在我们的函数式Java中,所有变量默认都是final的,(2)我们将变量称为符号(symbol)。

现在你可能会奇怪,用我们新创造的语言还能写出复杂的程序吗?如果每个符号都是不可变(non-mutalbe)的,我们就无法改变任何事情的状态!其实事实并非如此。在阿隆左研究lambda演算时,他并不想维护某个状态,并且在未来修改它。他关注的是如何对数据进行操作(这也通常被称为“演算体( caculating stuff)”。不管怎么说,既然lambda演算已被证明与图灵机等价,命令式程序能做的事情它应该也能做。但是我们应该怎么做呢? 其实函数式程序也能保存状态,只是它使用的是函数,而不是变量。函数式程序将状态保存在函数的参数中,而这些参数又保存在“栈”上。如果你想保存某个状态并且想每隔一段时间就去修改它,你可以写个递归函数。比如,我们可以写个能够翻转Java字符串的函数。记住,我们声明的每个变量默认都是final的。

String reverse(String arg) {
  if(arg.length == 0) { 
    return arg; 
  } else { 
    return reverse(arg.substring(1, arg.length)) + arg.substring(0,1); 
  } 
}

这个函数很慢而且特别消耗内存。它慢是因为它不停的调用自己,而它耗内存是因为它不断的分配对象。但是它确实是一个典型的函数式函数。你可能会问,怎么会有人这样写程序呢?下面就让我慢慢道来。

Leave a Reply

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