开发者

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

开发者 https://www.devze.com 2023-04-03 14:07 出处:网络
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 g

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.


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).


/: 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.


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

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号