实现基本的数组操作。
在函数式语言中,像length、map和reduce这样的数组操作非常常见。
请实现一系列基本的数组操作,不要使用现有的函数。
需要实现的操作的具体数量和名称会因你所在的编程语言轨道而异,以避免与现有名称冲突,但你将要实现的一般操作包括:
append(给定两个数组,把第二个数组中的所有元素添加到第一个数组的末尾);concatenate(给定一系列数组,把所有数组中的所有元素合并成一个扁平数组);filter(给定一个谓词和一个数组,返回所有满足 predicate(item) 为 True 的元素组成的数组);length(给定一个数组,返回其中元素的总数);map(给定一个函数和一个数组,返回对每个元素应用 function(item) 所得结果组成的数组);foldl(给定一个函数、一个数组和一个初始累加器,从左到右把每个元素折叠(归约)进累加器);foldr(给定一个函数、一个数组和一个初始累加器,从右到左把每个元素折叠(归约)进累加器);reverse(给定一个数组,返回一个包含所有原元素、但顺序相反的数组)。注意,传给折叠函数(foldl、foldr)的实参顺序很重要。
在 Java 中,一般认为使用实例方法比类方法更好。不过,在某些情况下,把函数写成 static 是完全合适的。由于 Java 中的类对修改是封闭的(也就是说,不能像在 Ruby 或 JavaScript 等语言中那样,在类定义之外给它添加成员),所以无法直接为这个类添加新行为。如果你仍然想为某个类型定义行为,该怎么办?这种情况下,惯用的做法是写一个工具方法。
这类方法的集合通常被称为“工具类”。JRE 中就有这样的类,比如 Arrays 和 Collections。
在这个练习中,我们希望 List 拥有 map()、reduce()、filter() 等方法。但 List 并没有这些方法,所以我们改用静态方法。
foldLeft 和 foldRight 方法属于“fold”函数,这个概念在函数式编程领域广为人知,但在面向对象领域就没那么常见了。参见维基百科上关于折叠的页面:总体背景和签名与实现提示。