请关注我的微信公众号
个人微信公众号
技术交流群 (仅作技术交流):642646237
请关注我的头条号:
折叠/化约在名称上变化最多,而且不同实现之间有着诸多微妙差异。
Scala语言——reduce
Scala需要更多地面对某些类型相关的场景,而这些场景在动态类型的Groovy和Clojure语言中根本不存在。因此Scala的化约相关的函数很丰富。
传给reduce()
的函数或运算符接受两个参数,且仅返回单一值,就好像原集合被“消耗”掉了一样。
Scala语言——reduceLeft
reduceLeft()
函数假定集合的第一个元素是运算的左值。
Scala语言——reduceRight
对于除法运算,运算次序是决定性的。如果希望调转运算进行的方向,可以改用reduceRight()
:
// 8 - 9 = -1
// 7 - (-1) = 8
// 6 - 8 = -2
// 5 - (-2) = 7
// 4 - 7 = -3
// 3 - (-3) = 6
// 2 - 6 = -4
// 1 - (-4) = 5
// result: 5
reduceRight()
调转的是运算的方向,而不是参数的次序。因此,它首先计算8 - 9,得到的结果再作为第二个参数参与后续的计算。
Scala语言——知道何时应该使用reduce
很重要
懂得什么时候应该使用像“reduce”这样的高层次抽象,是掌握函数式编程的一处关键所在。
Scala语言——化约操作和折叠操作的区别
化约操作和折叠操作在功能上存在交集。而就在它们的共同用途上,两者也有一处明显的区别。按照Scala的定义,reduceLeft[B >: A](op: (B, A) => B): B
的方法签名表明它只要求提供一个参数,即用来结合集合中元素的函数。起始值被指定为集合的第一个元素,不必另外提供。而方法签名foldLeft[B](z: B)(op: (B, A) => B): B
就要求提供一个起始值来作为后续计算的种子,这个另外提供的值同时也意味着返回值的类型可以不同于列表元素的类型。
Scala语言——foldLeft
和foldRight
运算符重载
foldLeft
和foldRight
分别各自对应的运算符/:
和:\
。
Groovy语言——inject
不带初始值
Groovy提供了两个版本的inject()
来完成化约操作,分别对应于Scala众多同类方法中的reduce()
和foldLeft()
。其中一个版本的inject()
允许传入初始值。
Groovy语言——inject
带初始值
Groovy的函数式类库远不如Scala和Clojure丰富。这一点并不奇怪,毕竟Groovy的定位是一种多范式语言,并不特别强调函数式编程能力。
Clojure语言
Clojure的基本定位就是一种函数式编程语言,所以它肯定支持(reduce )
。(reduce )
函数有一个可选的初始值参数,因此它其实涵盖了Scala中的reduce()
和foldLeft()
两种情况。
Clojure在它的Reducers库里提供了更多与化约操作相关的高级功能。
学习新范式中术语的困难
学习新范式(如函数式编程)的困难有一部分在于学习新的术语。假如遇到不同社群使用不同术语的情况,想搞清楚就更困难了。不过只要你抓住不同语言的共同点去观察,就能够看穿在形形色色的语法遮挡之下,其实功能大同小异。
网友评论