Return Expressions

    Expr1 ::=  ‘return’ [Expr]
A return expression return e must occur inside the body of some enclosing named method or function. The innermost enclosing named method or function in a source program, f, must have an explicitly declared result type, and the type of e must conform to it. The return expression evaluates the expression e and returns its value as the result of f. The evaluation of any statements or expressions following the return expression is omitted. The type of a return expression is scala.Nothing.
The expression e may be omitted. The return expression return is type-checked and evaluated as if it was return().
Read more, section 6.20.

return type


Return Expr and anonymous functions

    Expr1 ::=  ‘return’ [Expr]
An apply method which is generated by the compiler as an expansion of an anonymous function does not count as a named function in the source program, and therefore is never the target of a return expression.
Returning from a nested anonymous function is implemented by throwing and catching a scala.runtime.NonLocalReturnException. Any exception catches between the point of return and the enclosing methods might see the exception. A key comparison makes sure that these exceptions are only caught by the method instance which is terminated by the return.
If the return expression is itself part of an anonymous function, it is possible that the enclosing instance of f has already returned before the return expression is executed. In that case, the thrown scala.runtime.NonLocalReturnException will not be caught, and will propagate up the call stack.

return statement NonLocalReturnException syntax


MUST NOT use "var" inside a case class

Case classes are syntactic sugar for defining classes in which - all constructor arguments are public and immutable and thus part of the value's identity, have structural equality, a corresponding hashCode implementation and apply/unapply auto-generated functions provided by the compiler.
By doing this:
case class Sample(str: String, var number: Int)
You just broke its equality and hashCode operation. Now try using it as a key in a map.
As a general rule of thumb, structural equality only works for immutable things, because the equality operation must be stable (and not change according to the object's history). Case classes are for strictly immutable things. If you need to mutate stuff, don't use case classes.
"The Joy of Clojure": if any two mutable objects resolve as being equal now, then there’s no guarantee that they will a moment from now.
And if two objects aren’t equal forever, then they’re technically never equal ;-)

case-classes variables equals hashCode


Declaring abstract "var" members

It's a bad practice to declare abstract vars in abstract classes or traits. Do not do this:
trait Foo {
  var value: String
Instead, prefer to declare abstract things as def:
trait Foo {
  def value: String

// can then be overridden as anything
class Bar(val value: String) extends Foo
The reason has to do with the imposed restriction - a var can only be overridden with a var. The way to allow freedom to choose on inheritance is to use def for abstract members. And why would you impose the restriction to use a var on those that inherit from your interface. def is generic so use it instead.
Read more.

override best practices traits interfaces trait inheritance


Semicolons and infix operators

One issue with Scala’s semicolon convention is how to write expressions that span several lines. For instance
+ someOtherExpression
would be interpreted as two expressions:
+ someOtherExpression
To overcome this problem you could write the multi-line expression in parentheses, because semicolons are never inserted inside (...):
+ someOtherExpression)
Source: Coursera: Blocks and lexical scope



Public functions should have an explicit return type

Prefer this:
def someF(par1: T1, par2: T2): Result = {
To this:
def someF(par1: T1, par2: T2) = {
Yeah, type inference on the result of a function is great and all, but for public methods:
  • it's not OK to rely on an IDE or to inspect the implementation in order to see the returned type
  • Scala currently infers the most specialized type possible, because in Scala the return type on functions is covariant, so you might actually get a really ugly type back
For example, what is the returned type of this function:
def sayRunnable(name: String) = new Runnable {
  def sayIt() = println(s"Hello, $name")
  def run() = sayIt()
Do you think it's Runnable? Wrong, it's Runnable{def sayIt(): Unit}.

type inference


Value Definitions

Function parameters can be passed by value or be passed by name.
The same distinction applies to definitions.
The def form is “by-name”, its right hand side is evaluated on each use.
There is also a val form, which is “by-value”.
val x = 2
val y = square(x)
The right-hand side of a val definition is evaluated at the point of the definition itself.
Afterwards, the name refers to the value. For instance, y above refers to 4, not square(2).

by-name def


Value Definitions and Termination

The difference between val and def becomes apparent when the right hand side does not terminate.
def loop: Boolean = loop
A definition
def x = loop
is OK, but a definition
val x = loop
will lead to an infinite loop.

by-value definitions val termination


Rewrite rules for Booleans

Boolean expressions b can be composed of
true false // Constants
!b // Negation
b && b // Conjunction
b || b // Disjunction
and of the usual comparison operations:
e <= e, e >= e, e < e, e > e, e == e, e != e
Here are reduction rules for Boolean expressions (e is an arbitrary expression):
!true --> false
!false --> true
true && e --> e
false && e --> false
true || e --> true
false || e --> e
Note that && and || do not always need their right operand to be evaluated.
We say, these expressions use “short-circuit evaluation”.

expressions Boolean expressions reduction rules


Conditional Expressions

To express choosing between two alternatives, Scala has a conditional expression if-else. It looks like a if-else in Java, but is used for expressions, not statements.
def abs(x: Int) = if (x >= 0) x else -x
x >= 0 is a predicate, of type Boolean.
Here are reduction rules for conditional expressions (e1 and e2 are arbitrary expressions, b is boolean expression)
if (b) e1 else e2:
if (true) e1 else e2   --> e1
if (false) e1 else e2  --> e2

evaluation conditional expressions if-else

Loading rules...
Sign Up Now
or Subscribe for future quizzes