Scala Guide - Code Formatting

Back to Library

Originate’s Scala Guide

Code Formatting

Please read the Scala Style Guide carefully. The main points to consider are:

  1. Use two-space indentation. No tabs.

  2. Omit unnecessary blocks to reduce excessive nesting:

if (condition) { bad() }   if (condition) good

  1. Avoid wrapping lines. Split long lines into multiple expressions, assigning intermediate results to vals. When inevitable, indent wrapped lines with two spaces:

val iAm = aVeryLong + expression + thatTakes + multipleLines

  1. Use lower camel case for valName, varName, methodName, functionObject, packageObject, and annotationName.

  2. Use upper camel case for ConstantName, EnumerationValue, ClassName, TraitName, ObjectName, TypeParameter.

  3. No UPPERCASE_UNDERSCORE, not even for constants or type parameters.

  4. No get/set prefixes for accessors and mutators.

  5. Always use empty parentheses when, and only when, declaring or calling methods with side-effects.

  6. Unless an established convention already exists (e.g, mathematical symbols), avoid symbolic method names (“operators”).

  7. Use type inference where possible. But put clarity first and favor explicitness when an inferred type may not be obvious.

val good = 1 // Int, obviously   val bad = config.get("key") // What does it return? val better: Option[String] = config.get("key"

  1. Opening curly braces ({) must be on the same line as the declaration.

  2. Constructors should be declared all on one line. If not possible, put each constructor argument on its own line, indented four spaces.

  3. Extensions follow the same rule above, but indent two spaces to provide visual separation between constructor arguments and extensions:

class Platypus( name: String, age: Int) extends Beaver with Duck

  1. Favor short, single-expression, single-line method bodies.

  2. No procedure syntax.

def bad() { ??? } def worse { ??? }   def good(): Unit = { ??? }

  1. Postfix operator notation is unsafe and shall not be used. Consider it deprecated. Never import scala.language.postfix!

val bad = seq mkString   val good = seq.mkString

  1. Always use infix notation for methods with symbolic names or higher-order functions (map, foreach, etc.).

val bad = seq.map(_ * 2)   val good = seq map (_ * 2

When the syntax does not allow it, stick to traditional method invocation syntax:

val bad = (seq map f).toSet // Starts to read like LISP   val good = seq.map(f).toSet

Additions and Deviations

  1. Text file format: UTF-8, no BOM, Unix line endings (LF, ‘\n’), newline at EOF. Use the .editorconfig (http://editorconfig.org/) profile inside the skeleton folder to configure your editor.

  2. 100 characters maximum line length.

  3. One blank line between method, class, and object definitions.

  4. Use blank lines between statements and declarations to create logical groupings.

  5. No double blank lines, anywhere.

  6. No trailing whitespace at the end of lines, they cause problems when diffing between files or between versions. Configure your text editor to do this for you automatically.

  7. In general, obey English rules and mathematical conventions for punctuation:

  8. A single space after and no space before ,, :, ;, ), etc.

  9. A single space before (, except for method invocation or declaration. Never a space after.

  10. Single spaces around =, +, -, *, {, }, =>, <-, etc.

  11. No spaces between consecutive ( or ).

  12. Do not align vertically: it requires constant realignments, making diffs longer.

  13. Methods must always have explicit return types. Explicitly declaring the return type allows the compiler to verify correctness.

  14. Modifiers should be declared in the following order: override, abstract, private or protected, final, sealed, implicit, lazy.

  15. Put imports at the top of the file. Imports should be grouped from most to least specific:
    1. The project’s own classes
    2. Frameworks and libraries: com.*, net.*, org.*, etc.
  16. scala.*
    1. java.* and javax.*

Inside each group, packages and classes must be sorted alphabetically. Separate groups with blank lines:

import myapp.util.StringUtils   import org.joda.time.DateTime   import play.api.Configuration   import scala.concurrent.Future   import java.net.URI

The script fix-imports.go in the skeleton project folder can be used to help you organize your imports.

  1. Do not use relative imports. Full imports are easier to search, and never ambiguous:

package foo.bar   // Bad import baz.Qux   // Good import foo.bar.baz.Qux

  1. Do not wildcard-import entire packages: import bad._

  2. The bigger the scope, the more descriptive the name. Only for very small, local scopes may single-letter mnemonics be used.

  3. Use _ for simple, single line functions:

val bad = seq filter (number => number % 2 == 0)   val good = seq filter (_ % 2 == 0

  1. Omit the _ for functions that take a single argument:

bad foreach println(_)   good foreach printl

  1. The formatting rules for constructors (four-space double indent) also apply to method declarations:

def delta( a: Int, b: Int, c: Int): Int = { b * b - 4 * a * c }

  1. Use infix notation for single argument methods on monadic types (contains, getOrElse, etc.)

  2. For single-line functions and for-comprehensions, use parentheses. For multiline ones, use brackets:

for (i <- 1 to 3) println(i)   seq map (_ * 2)   seq map { a => if (a < 0) -a else a }

  1. Whenever possible, simplify pattern matching expressions by omitting the match keyword and using partial functions:

bad map { _ match { case 1 => "one" case _ => "not one" } }   good map { case 1 => "one" case _ => "not one" }

  1. When passing functions, do not use inner block syntax:

(bad => { ??? })   { good => ??? }

  1. For documentation comments, use Javadoc left-hand margin style instead of the Scaladoc convention:

/** Bad * convention */   /** * Good * convention */

  1. Optimize for readability. Readability trumps consistency (but not by much). Consistency trumps everything else.
Back to Library