Подтвердить что ты не робот

Scala - инфикс против точечной нотации

Есть ли передовая практика для другой? Я читал книгу Scala Odersky, et al. и кажется, что infix используется для многих функций API коллекций, тогда как точка зарезервирована для определенных пользователем функций.

4b9b3361

Ответ 1

У меня лично нет жестких и быстрых правил для этого, но я обычно использую нотацию infix только с именами символических методов и точечной нотации для буквенно-цифровых символов.

Обозначение Infix делает более громоздкой модификацию кода позже. Вот несколько примеров.

Представьте, что у вас есть эта строка кода:

xs filter { f } map { g }

Предположим, что в какой-то момент времени вам нужно добавить конец toList. Вы так выразились:

xs filter { f } map { g } toList

Это может привести к проблемам с точкой с запятой. Чтобы избежать этих проблем, вы либо положили точку с запятой, либо положили новую строку. На мой взгляд, оба варианта уродливы. Чтобы избежать всей этой бессмыслицы, я предпочитаю идти с xs.filter(f).map(g). Всегда проще рефакторировать этот синтаксис.

Другой пример: Скажем, в моем коде есть следующее:

if(foo contains bar) { ..

Скажем, мне нужно отменить условие. Если я изменю его следующим образом:

if(!foo contains bar) { ..

Облом. Это анализируется как (!foo).contains(bar). Не то, что мы хотели.

Или предположим, что вам нужно дополнительно добавить новое условие, и вы измените его так:

if(foo contains bar && cond) { ..

Еще один облом. Это анализируется как foo.contains(bar.&&(cond)). Не то, что мы хотели, снова.

Конечно, вы могли бы добавить кучу круглых скобок, но это было бы уродливо и трудно читать/редактировать по сравнению с точечной нотацией.

Теперь все, что я сказал выше, относится и к именам символических методов. Однако символические методы выглядят неестественно при использовании с синтаксисом точек, и поэтому я предпочитаю синтаксис инфикса для них.


Одно исключение из приведенного выше руководства: внутренние DSL. Они обычно обрабатываются с осторожностью, чтобы не вызывать проблемы с анализом, если они написаны так, как это указано в их документации/примерах (в которых обычно используется инфиксная нотация).

Ответ 2

Это вопрос личных предпочтений. Ваше решение использовать один стиль или другое должно основываться на том, что делает ваш код наиболее читаемым.

Но обратите внимание, что возможность оставить точку и круглые скобки ограничена только некоторыми синтаксическими конструкциями, поэтому иногда вам просто нужно вернуться к их использованию.

Ответ 3

В официальной документации по сайту Scala есть хорошее руководство , в котором описывается правильная нотация инфиксного использования над точечной нотацией.

Обозначение суффикса:

names.toList
// is the same as
names toList // Unsafe, don't use!

Arity-1:

// right!
names foreach (n => println(n))
names mkString ","
optStr getOrElse "<empty>"
// wrong!
javaList add item

Функции более высокого порядка:

// wrong!
names.map (_.toUpperCase).filter (_.length > 5)
// right!
names map (_.toUpperCase) filter (_.length > 5)

Символические методы/Операторы:

// right!
"daniel" + " " + "Spiewak"
// wrong!
"daniel"+" "+"spiewak"

Ответ 4

Я обнаружил, что использование нотации infix для map прекрасно работает, когда я создаю декартес с библиотекой cats. например:.

(fetchIt(1) |@| fetchIt(2) |@| fetchIt(3)).map(MyCaseClass)

вы можете избавиться от окружающих круглых скобок, например:

fetchIt(1) |@| fetchIt(2) |@| fetchIf(3) map MyCaseClass

и, на мой взгляд, второй вариант лучше читается. Полагаю, вкус. Просто хотел добавить стоимость моих двух центов.

Вышеупомянутое работает, потому что | в "| @|" имеет более высокий приоритет, чем m в "карте". Прочтите эту часть спецификации Scala lang, чтобы узнать подробнее:

Если в выражении имеется несколько операций инфикса, то операторы с более высоким приоритетом связывают более тесно, чем операторы с более низким старшинство.

http://scala-lang.org/files/archive/spec/2.12/06-expressions.html#infix-operations