Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Scala Vector fold syntax (/: and :\ and /:\)

Tags:

syntax

scala

fold

Can someone provide some examples for how

/: :\ and /:\

Actually get used? I assume they're shortcuts to the reduce / fold methods, but there's no examples on how they actually get used in the Scala docs, and they're impossible to google / search for on StackOverflow.

like image 559
chbrown Avatar asked Sep 07 '11 19:09

chbrown


3 Answers

/: is a synonym for foldLeft and :\ for foldRight.

But remember that : makes /: apply to the object to the right of it.

Assuming you know that (_ * _) is an anonymous function that's equivalent to (a, b) => a * b, and the signature of foldLeft and foldRight are

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

i.e. they're curried functions taking a start value and a function combining the start value / accumulator with an item from the list, some examples are:

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

which is the same as

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

And

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

in infix notation is

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

which is the same as

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

Add your own collections and functions and enjoy!

The thing to remember with the short (/: and :\) notations is that, because you're using the infix notations you need to put parentheses around the first part in order for it to pick up the second argument list properly. Also, remember that the functions for foldLeft and foldRight are the opposite way round, but it makes sense if you're visualising the fold in your head.

like image 21
Luigi Plinge Avatar answered Oct 18 '22 02:10

Luigi Plinge


I personally prefer the /: and :\ forms of foldLeft and foldRight. Two reasons:

  1. It has a more natural feel because you can see that you are pushing a value into the left/right of a collection and applying a function. That is

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

    Are both equivalent, but I tend to think the former emphasises my intuition as to what is happening. If you want to know how this is happening (i.e. the method appears to be called on the value 1, not the collection), it's because methods ending in a colon are right-associative. This can be seen in ::, +: etc etc elsewhere in the standard library.

  2. The ordering of the Function2 parameters is the same order as the folded element and that which is folded into:

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

    Better in every way than:

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

    Although I admit that this was a far more important difference in the era before decent IDE support: nowadays IDEA can tell me what function is expected with a simple CTRL-P

I hope it should also be obvious how :\ works with foldRight - it's basically exactly the same, except that the value appears to be being pushed in from the right hand side. I must say, I tend to steer well clear of foldRight in scala because of how it is implemented (i.e. wrongly).

like image 97
oxbow_lakes Avatar answered Oct 18 '22 00:10

oxbow_lakes


Rex Kerr has written nice answer about folds here. Near the end you can see an example of shortcut syntax of foldLeft and foldRight.

like image 3
om-nom-nom Avatar answered Oct 18 '22 02:10

om-nom-nom