函数式思维:大量转换:同义词掩盖了相似性2013-10-07 IBM Neal Ford函数式编程语言实现代码重用的方法与面向对象的语言不同,这个主题我在 “第 2 部分” 中进行了分析。面向对象的 语言往往拥有众多可进行多种操作的数据结构,而函数式语言却只有极少数可进行多种操作的数据结构。面向对象的语言鼓 励您创建特定于类的方法,而您可以捕获一些重复出现的模式,以便以后重用。函数式语言鼓励您将常见转换应用于数据结 构,使用更高级的函数来定制特定实例的操作,从而帮助您实现重用。相同的数据结构和操作出现在所有函数式语 言中(也出现在支持 Java 中的函数式编程的众多框架中),但它们的名称通常是不同的。容易导致混淆的命名方式使得将 一种语言的知识转换成另一种语言的知识变得十分困难,即使基础概念是完全相同的。本期文章的目标是让这种转 换变得简单一些。本文引入了一个简单问题,该问题要求制定一些策略并进行迭代,使用五种语言(Java、Groovy、 Clojure、JRuby 和 Scala)和两种 Java 函数式框架(Functional Java 和 Totally Lazy)来实现该解决方案。每种语言 的实现都是相同的,但相关细节具有很大的出入。普通 Java本文涉及的问题是如何确定某个整数是否是质 数,质数的因数只能是 1 及其本身。确定质数的算法有好几种(一些替代解决方案可在 “第 1 部分” 中找到);我将使 用这样一种解决方案:首先确定数字的因数,然后检查所有因数的和是否等于该数字加1,从而确定该数字是否为质数。这 并非最高效的算法,但我的目的是展示常用集合方法的不同实现,而非效率。清单 1 显示了普通的 Java 版本:清单 1. 普通的 Java 质数分类器
public class PrimeNumberClassifier {private Integer number;public PrimeNumberClassifier(int number) {this.number = number;}public boolean isFactor(int potential) {return number % potential == 0;}public Set<Integer> getFactors() {Set<Integer> factors = new HashSet<Integer>();factors.add(1);factors.add(number);for (Integer i = 2; i < number; i++)if (isFactor(i))factors.add(i);return factors;}public int sumFactors() {int sum = 0;for (int i : getFactors())sum += i;return sum;}public boolean isPrime() {return sumFactors() == number + 1;}}
如果您阅读过以前的函数式思维 系列文章,就会觉得 清单 1 中 getFactors() 方法中的算法很熟悉,这种算 法对候选因数进行了筛选。