Skip to content
This repository has been archived by the owner on Nov 22, 2017. It is now read-only.

Scala Guide

Fehmi Can Sağlam edited this page Mar 18, 2015 · 4 revisions
  • Limit lines to 120 characters.
  • The only exceptions are import statements and URLs (although even for those, try to keep them under 120 chars).
  • Use 2-space indentation in general.

    if (true) {
      println("Wow!")
    }
  • Do NOT use vertical alignment. They draw attention to the wrong parts of the code and make the aligned code harder to change in the future.

    // Don't align vertically
    val plus     = "+"
    val minus    = "-"
    val multiply = "*"
    
    // Do the following
    val plus = "+"
    val minus = "-"
    val multiply = "*"

Scala type inference, especially left-side type inference and closure inference, can make code more concise. That said, there are a few cases where explicit typing should be used:

  • Public methods should be explicitly typed, otherwise the compiler's inferred type can often surprise you.
  • Implicit methods should be explicitly typed, otherwise it can crash the Scala compiler with incremental compilation.
  • Variables or closures with non-obvious types should be explicitly typed. A good litmus test is that explicit types should be used if a code reviewer cannot determine the type in 3 seconds.

Do NOT use implicits, unless:

  • you are building a domain-specific language
  • you are using it for implicit type parameters (e.g. ClassTag, TypeTag)
  • you are using it private to your own class to reduce verbosity of converting from one type to another (e.g. Scala closure to Java closure)

When implicits are used, we must ensure that another engineer who did not author the code can understand the semantics of the usage without reading the implicit definition itself. Implicits have very complicated resolution rules and make the code base extremely difficult to understand. From Twitter's Effective Scala guide: "If you do find yourself using implicits, always ask yourself if there is a way to achieve the same thing without their help."

If you must use them (e.g. enriching some DSL), do not overload implicit methods, i.e. make sure each implicit method has distinct names, so users can selectively import them.

// Don't do the following, as users cannot selectively import only one of the methods.
object ImplicitHolder {
  def toRdd(seq: Seq[Int]): RDD[Int] = ...
  def toRdd(seq: Seq[Long]): RDD[Long] = ...
}

// Do the following:
object ImplicitHolder {
  def intSeqToRdd(seq: Seq[Int]): RDD[Int] = ...
  def longSeqToRdd(seq: Seq[Long]): RDD[Long] = ...
}
Clone this wiki locally