2011-09-07 86 views
15

有人可以提供一些如何斯卡拉矢量倍语法(/:和:和/:)

/::\ and /:\

实际上例子习惯?我假设他们是reduce/fold方法的捷径,但没有关于如何在Scala文档中实际使用的示例,并且他们无法在Google/StackOverflow上进行搜索。

+0

也称为折叠(foldl),折叠右边(foldr)并折叠任何(??)。维基百科在[fold hofs](http://en.wikipedia.org/wiki/Fold_%28higher-order_function%29)上有一些一般信息和漂亮的图片。 – 2011-09-07 19:44:10

回答

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 

即他们是咖喱职能采取起始值并结合启动值的函数从列表中的项目/累加器,一些例子是:

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的功能是相反的,但是如果您想要将头部折叠可视化,则这很有意义。

+0

忘了说,'/:\'是'fold'的同义词,当你不关心顺序时它是用于折叠的。语法与':\'相同。我从来没有用过它,但我认为它对平行集合很有用,所以你可以在多个线程/ actor之间拆分折叠操作。 –

3

雷克斯克尔已经写了关于折叠here很好的答案。接近尾声时,您可以看到foldLeft和foldRight的快捷语法示例。

14

我个人更喜欢/::\形式的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一起工作 - 它基本上完全相同,除了值似乎是从右侧推入。我必须说,我倾向于在scala中清除foldRight,因为它是如何实现的(即错误地)。

+0

你说服了我。我正在切换到/:从现在开始。 –