17

有人可以提供一些例子来说明如何

/: :\/:\

真的习惯了吗?我认为它们是 reduce / fold 方法的快捷方式,但没有关于它们如何在 Scala 文档中实际使用的示例,并且无法在 StackOverflow 上搜索 / 搜索它们。

4

3 回答 3

14

我个人更喜欢and的/:and:\形式。两个原因:foldLeftfoldRight

  1. 它有一种更自然的感觉,因为您可以看到您正在将一个值推入集合的左/右并应用一个函数。那是

    (1 /: ints) { _ + _ }
    
    ints.foldLeft(1) { _ + _ }
    

    两者都是等价的,但我倾向于认为前者强调了我对正在发生的事情的直觉。如果您想知道这是如何发生的(即该方法似乎是在值 1 上调用的,而不是在集合上),那是因为以冒号结尾的方法是右关联的。这可以在标准库的其他地方看到::+:等等。

  2. 参数的Function2顺序与折叠元素的顺序相同,并且折叠成:

       (b /: as) { (bb, a) => f(bb, a) }
     // ^    ^      ^   ^
     // ^    ^      ^   ^
     // B    A      B   A
    

    在各方面都比:

    as.foldLeft(b) { (bb, a) => f(bb, a) }
    

    虽然我承认这在 IDE 支持之前的时代是一个更重要的区别:现在,IDEA 可以通过简单的 CTRL-P 告诉我预期的功能

我希望它也应该很明显如何:\使用 foldRight - 它基本上完全相同,只是该值似乎是从右侧推入的。我必须说,我倾向于避开foldRightscala,因为它是如何实现的(即错误地)。

于 2011-09-07T20:18:08.340 回答
10

/:foldLeft:\的同义词foldRight

但请记住,:/:适用于它右侧的对象。

假设您知道这(_ * _)是一个等效于 的匿名函数(a, b) => a * b,并且 foldLeft 和 foldRight 的签名是

def foldLeft  [B] (z: B)(f: (B, A) ⇒ B): B 
def foldRight [B] (z: B)(f: (A, B) ⇒ B): B 

即它们是 curried 函数,采用起始值和将起始值/累加器与列表中的项目相结合的函数,一些示例是:

List(1,2,3).foldLeft(1)(_*_)

这与

(1 /: List(1,2,3))(_*_)

List(1,2,3).foldRight(1)(_*_)

中缀表示法是

(List(1,2,3) foldRight 1)(_*_)

这与

(List(1,2,3) :\ 1)(_*_)

添加您自己的收藏和功能,尽情享受吧!

使用短 (/::\) 符号要记住的是,因为您使用的是中缀符号,所以您需要在第一部分周围加上括号,以便它正确地选择第二个参数列表。另外,请记住 foldLeft 和 foldRight 的函数是相反的,但如果您在脑海中想象折叠,这是有道理的。

于 2011-09-07T20:04:03.863 回答
3

Rex Kerr 在这里写了关于折叠的好答案。在接近尾声时,您可以看到 foldLeft 和 foldRight 的快捷语法示例。

于 2011-09-07T19:53:03.277 回答