Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>Having multiple classes and objects inside a single file is considered good form in Scala, as long as the classes are tightly related.</p> <p>While not necessary, the type returned by a method -- a named function declared on a trait, class or object -- is expected to be declared for non-private methods. Spaces are expected after <code>:</code>, but not before it. </p> <pre><code>// 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)) } </code></pre> <p>Spaces are expected between keywords and parenthesis, but not between a method name and the following parenthesis, in dot notation. For operator notation, there doesn't seem to be an accepted style regarding parenthesis -- or when to use that notation, for that matter, but spaces are expected around non-alphanumeric methods in such notation.</p> <pre><code>// keywords if (foo) ... // dot notation foo.doSomething(bar) // operator notation foo doSomething bar foo + bar </code></pre> <p>Exceptionally, when concatenating strings with <code>+</code>, the recommended style is not to use spaces around it. For example:</p> <pre><code>// concatenate strings println("Name: "+person.name+"\tAge: "+person.age) </code></pre> <p>Declarations that can be one-liners are expected to be one-liners, unless the nesting isn't obvious.</p> <pre><code>// one-liners lazy val foo = calculateFoo def square(x: Int) = x * x </code></pre> <p>Methods that do not expect parameters, and do not have side effects, are supposed to be used without parenthesis, except for Java methods, which are expected to be used with parenthesis. Parameter-less methods with side effects are supposed to be used with parenthesis.</p> <pre><code>// without side-effects val x = foo.length val y = bar.coefficient // with side-effects foo.reverse() </code></pre> <p>Declarations which contains a single expression are expected not to be enclosed inside curly braces unless other syntactic considerations make that impossible. Enclosing an expression within parenthesis to enable multi-line expressions is accepted, but I have seen little use of that.</p> <pre><code>// single-line expression def sum(list: List[Int]): Int = if (!list.isEmpty) list reduceLeft (_ + _) else 0 // multi-line expression val sum = ( getItems reduceLeft (_ + _) ) </code></pre> <p>In for-comprehensions, keeping generators and conditions vertically aligned seems to be an accepted style. As for <code>yield</code>, I have seen it both aligned with <code>for</code> and indented.</p> <pre><code>// for-comprehensions val squares = for (x &lt;- numbers) yield x * x // Curly brackets-style identation val cells = for { x &lt;- columns y &lt;- rows if x != y } yield Cell(x, y) // Parameter-style identation val cells = for (x &lt;- columns; y &lt;- rows; if x != y) yield Cell(x, y) </code></pre> <p>It's also accepted style to vertically align parameters of a class declaration. </p> <p>Speaking of indentation, two-spaces is the accepted convention.</p> <p>Curly braces are expected to start on the same line of the declaration, and end vertically aligned with that line by itself.</p> <pre><code>// another example def factorial(n: Int): Int = { def fact(n: Int, acc: Int): Int = n match { case 0 =&gt; acc case x =&gt; fact(x - 1, x * acc) } fact(n, 1) } </code></pre> <p>For procedures -- functions whose return type is <code>Unit</code> --, the expected style was supposed to be to leave out the type of the method and the equal sign:</p> <pre><code>// procedures def complain { println("Oh, no!") } </code></pre> <p>Some people think this style is error prone, however, as a missed equal sign will change a function returning something other than <code>Unit</code> into a procedure.</p> <p>Identifiers are written in camel case (eg: <code>identifiersHaveHumps</code>), like in Java. For names of fields, method parameters, local variables and functions, start with a lower case letter. For classes,traits and types, start with an upper case letter.</p> <p>Departing from Java convention are constant names. In Scala, the practice is to use standard camel case starting with an upper case letter. For example <code>Pi</code> and not <code>PI</code>, XOffset and not <code>X_OFFSET</code>. This rule is usually followed by any singleton. Having a constants and singletons be represented that way has a practical consequence, for case matches:</p> <pre><code>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 =&gt; println("I got a true Pi."); true case pi =&gt; println("I got "+pi+" and bounded it to an identifier named pi."); false } </code></pre> <p>Package names are written beginning with a lower case letter. This is particularly helpful when distinguishing in an import statement what is a package and what is not. In the previous example, <code>Math</code> is not a package (it's a singleton), as it begins with an upper case letter.</p> <p>Using the underline character -- <code>_</code> -- is not recommended, as that character has many special meanings in Scala. These rules for identifiers can be found on pages 141 and 142 of Programming in Scala, by Odersky, Spoon &amp; Venners.</p> <p>Right now, I can't recall other situations, but feel free to ask for clarification on specific points. Some of these rules were explicitly stated, others are more of a community consensus. I tried to leave out my own preferences, but I may have failed.</p> <p>More importantly, perhaps, there just isn't really much of an unified convention. One reason for that may be that Scala is attracting people from many very different backgrounds, such as functional language mavens, Java programmers and web 2.0 enthusiasts.</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload