None
instead of Some(null)
SC-A1002It is more idiomatic in scala to use Option
, i.e. Some
and None
instead of null
. Using Some(null)
instead of None
defeats the entire purpose of Option
. However, there might be certain scenarios where this is a legitimate approach, such as when dealing with Java-based libraries, to improve compatibility.
Carefully consider whether using Option
with null
is necessary before doing so.
Scala allows you to import entities from same package in separate statements. However, it is generally recommended that you group such imports together. Doing so makes the code more readable and easier to navigate.
Enum values are always accessed using the enum's name. Therefore, it does not make any sense to prefix the enum's values with the enum's name. Doing so is repetitive and adds noise to the code.
infix
modifier is redundant for symbol-like methods SC-R1089infix
modifier is a new modifier introduced in Scala 3 that can be applied to methods.
This allows you to use the method as an infix operation. However, symbol-like methods are by default allowed in infix operations and do not require this modifier.
Since this makes the modifier redundant, it is recommended that you drop the said modifier for such methods.
final
modifier is redundant for object
SC-R1053A class cannot extend an object thereby making the final
modifier redundant. It is therefore recommended that you drop the said modifier.
Default values are values that are used in case the user does not explicitly supply a value. It is always recommended that you place these default values at last. Placing them at the beginning or in the middle makes it difficult to skip them when invoking the method.
Scala allows you to inherit from scala.App
(which uses DelayedInit
) to set up a simple and small Main
program. However, since DelayedInit
is now deprecated, it is recommended that you define a suitable entry point of your own.
Unary methods in Scala are special methods that are used to define unary operators on types. Because unary operators do not take in any arguments and operate on a single entity, declarations of such operators should not define parameters, or have parentheses either.
Scala 2 used the syntax entity_:*
to define vararg splices. However, Scala 3 has changed this syntax to entity*
. While both kinds of syntax are valid in
Scala 3 for now, this behavior is likely to change in the near future. Consider migrating to the newer syntax as soon as possible.
as
keyword for import aliases SC-R1081Scala 2 used the =>
token in import aliases. However, Scala 3 has changed this syntax and now recommends that you use the as
keyword instead.
While both the syntaxes are valid in the present Scala 3 versions for now, it is likely going to change in the near future.
Consider migrating to the newer syntax as soon as possible.
if
statement where possible SC-R1082Instead of assigning values in the then and else clauses of an if
statement, consider using the if
statement itself as an expression.
This allows you to directly assign the returned value to a val
. This syntax is clear and simpler.
Classes that are either case
or that implement the unapply()
method allow you to utilize pattern matching. However, in this case, all the patterns specified in the pattern matching are wildcard patterns. Either this is a mistake or you meant to simply match a specific type. In the latter's case, consider using the syntax v: Tpe
.
java.lang.Error
SC-R1045Error
s represent situations that are difficult to recover from. Therefore, it is recommended that you do not extend java.lang.Error
and instead inherit from java.lang.Exception
to denote custom errors/exceptions.
AutoCloseable
for closing resources SC-R1052The highlighted close
method functionally resembles that of AutoCloseable
's. AutoCloseable
is an interface that classes can inherit in scenarios where they hold resources that are to be closed. Consider refactoring your code to utilize this interface if possible.
filter().headOption
as find()
SC-P1006The scala analyzer has determined that this collection method chain can be simplified into a single call to find()
.
Use anonymous function when pattern matching element(s) rather than explicitly using the match
keyword when possible. This approach/syntax is cleaner, improves readability and is easy to comprehend.
Option.isDefined
, Option.isEmpty
or Option.nonEmpty
instead of Option.size
SC-R1004Scala's collections return either Some
or None
when retrieving elements depending on whether the requested element exists or not. Therefore, the idiomatic and right approach is to use Option.isDefined
, Option.isEmpty
or Option.nonEmpty
instead of Option.size
.
getOrElse()
on get()
SC-R1005get()
is used to index data structures such as Map
to retrieve values. Such structures also provide an additional method, getOrElse(),
that additionally allows you to provide a default value to use if the requested key is nonexistent. While get()
returns an Option[Type]
which may be Some(value)
or None
depending on whether the value exists, getOrElse()
will directly return a value of the correct type. If you need to supply a default value for nonexistent entries, it is more succinct and maintainable to use getOrElse()
on the collection itself instead of chaining getOrElse()
after get()
.
filter().isEmpty
with !exists()
SC-R1007filter()
allows you to select elements from your collection that satisfy the provided condition/predicate. In situations where you need to check if there are any elements satisfying your condition, it is suggested that you directly use !exists()
over filter().isEmpty
as the former is slightly more efficient, readable, and easy to maintain.
filter().size
with count()
SC-R1008filter()
allows you to select elements from your collection that satisfy the provided condition/predicate. In situations where you need to count the number of elements satisfying your condition, it is suggested that you directly use count()
over filter().size
as the former is slightly more efficient, readable and easy to maintain.