Ответ 1
Наличие нескольких классов и объектов внутри одного файла считается хорошей формой в Scala, если классы тесно связаны.
В то время как нет необходимости, ожидается, что тип, возвращаемый методом - именованная функция, объявленная по признаку, классу или объекту, будет объявлена для не-частных методов. Пробелы ожидаются после :
, но не раньше.
// methods declared on a class, trait or object
def length: Int = ...
def multiply(other: Foo): Foo = ...
def hypotenuse(a: Double, b: Double): Double = {
// function inside a method, so effectively private
def square(x: Double) = x * x
math.sqrt(square(a) + square(b))
}
Пробелы ожидаются между ключевыми словами и скобками, но не между именем метода и следующей скобкой, в точечной нотации. Для обозначения оператора, похоже, не существует принятого стиля в отношении скобок - или когда использовать эту нотацию, если на то пошло, но в таких обозначениях ожидаются пробелы в не-алфавитно-цифровых методах.
// keywords
if (foo) ...
// dot notation
foo.doSomething(bar)
// operator notation
foo doSomething bar
foo + bar
В исключительных случаях при конкатенации строк с помощью +
рекомендуемый стиль не должен использовать пробелы вокруг него. Например:
// concatenate strings
println("Name: "+person.name+"\tAge: "+person.age)
Объявления, которые могут быть однострочными, должны быть однострочными, если вложенность не очевидна.
// one-liners
lazy val foo = calculateFoo
def square(x: Int) = x * x
Методы, которые не ожидают параметров и не имеют побочных эффектов, предполагается использовать без круглых скобок, за исключением методов Java, которые, как ожидается, будут использоваться с круглыми скобками. Предполагается, что с помощью круглых скобок используются методы без параметров с побочными эффектами.
// without side-effects
val x = foo.length
val y = bar.coefficient
// with side-effects
foo.reverse()
Объявления, содержащие одно выражение, не должны быть заключены внутри фигурных скобок, если другие синтаксические соображения не делают этого невозможным. Включение выражения в круглые скобки для включения многострочных выражений принимается, но я мало использовал это.
// single-line expression
def sum(list: List[Int]): Int = if (!list.isEmpty) list reduceLeft (_ + _) else 0
// multi-line expression
val sum = (
getItems
reduceLeft (_ + _)
)
В целях понимания, сохранение генераторов и условий, выровненных по вертикали, кажется приемлемым. Что касается yield
, я видел, что он совмещен с for
и отступом.
// for-comprehensions
val squares =
for (x <- numbers)
yield x * x
// Curly brackets-style identation
val cells = for {
x <- columns
y <- rows
if x != y
} yield Cell(x, y)
// Parameter-style identation
val cells = for (x <- columns;
y <- rows;
if x != y)
yield Cell(x, y)
Он также принял стиль для вертикального выравнивания параметров объявления класса.
Говоря об отступе, два пространства являются принятым соглашением.
Ожидается, что фигурные скобки начинаются с одной и той же строки декларации и заканчиваются вертикально в соответствии с этой линией.
// another example
def factorial(n: Int): Int = {
def fact(n: Int, acc: Int): Int = n match {
case 0 => acc
case x => fact(x - 1, x * acc)
}
fact(n, 1)
}
Для процедур - функций, тип возврата которых Unit
-, ожидаемый стиль должен был исключать тип метода и знак равенства:
// procedures
def complain {
println("Oh, no!")
}
Некоторые люди считают, что этот стиль является склонным к ошибкам, поскольку знак пропущенного равенства изменит функцию, возвращающую в процедуру что-то другое, кроме Unit
.
Идентификаторы записываются в виде верблюда (например: identifiersHaveHumps
), как в Java. Для имен полей, параметров метода, локальных переменных и функций начинайте с строчной буквы. Для классов, признаков и типов начинайте с буквы верхнего регистра.
Отступ от соглашения Java - это постоянные имена. В Scala практика заключается в использовании стандартного верблюжьего корпуса, начинающегося с буквы верхнего регистра. Например Pi
, а не Pi
, XOffset и не X_OFFSET
. За этим правилом обычно следует любой синглтон. Представление констант и синглтонов таким образом имеет практическое значение для совпадений:
import scala.Math.Pi
val pi = Pi // this identifier will be shadowed by the identifier in the function below
def isPi(n: Double): Boolean = n match {
case Pi => println("I got a true Pi."); true
case pi => println("I got "+pi+" and bounded it to an identifier named pi."); false
}
Имена пакетов начинаются с буквы нижнего регистра. Это особенно полезно при различении в заявлении на импорт того, что такое пакет, а что нет. В предыдущем примере Math
не является пакетом (это singleton), так как он начинается с буквы верхнего регистра.
Использование символа подчеркивания - _
- не рекомендуется, так как этот символ имеет много специальных значений в Scala. Эти правила для идентификаторов можно найти на страницах 141 и 142 программирования в Scala, Odersky, Spoon и Venners.
Сейчас я не могу вспомнить другие ситуации, но не стесняйтесь просить разъяснения по конкретным вопросам. Некоторые из этих правил были четко сформулированы, другие - скорее из сообщества. Я попытался оставить свои предпочтения, но я, возможно, потерпел неудачу.
Что еще более важно, возможно, просто не очень много единого соглашения. Одной из причин этого может быть то, что Scala привлекает людей из самых разных слоев, таких как функциональные языковые mavens, программисты Java и энтузиасты web 2.0.