Сложный векторный синтаксис Scala (/: и: \ and /: \) - PullRequest
15 голосов
/ 07 сентября 2011

Может ли кто-нибудь привести некоторые примеры того, как

/: :\ и /:\

На самом деле привыкнуть?Я предполагаю, что они являются ярлыками для методов уменьшения / сгиба, но нет примеров того, как они на самом деле используются в документах Scala, и их невозможно найти в Google / искать в StackOverflow.

Ответы [ 3 ]

14 голосов
/ 08 сентября 2011

Я лично предпочитаю формы /: и :\ foldLeft и foldRight. Две причины:

  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 - это в основном то же самое, за исключением того, что значение, похоже, вводится с правой стороны. Должен сказать, я стараюсь держаться подальше от foldRight в scala из-за того, как он реализован (то есть неправильно).

10 голосов
/ 08 сентября 2011

/: является синонимом 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 противоположны, но это имеет смысл, если вы визуализируете сгиб в своей голове.

3 голосов
/ 07 сентября 2011

Рекс Керр написал хороший ответ о сгибах здесь . Ближе к концу вы можете увидеть пример сокращенного синтаксиса foldLeft и foldRight.

...