1. Overview
In this tutorial, we’re going to look at some basic Scala operators. We’ll go through the rules of operator precedence and associativity.
2. Methods & Operators
In Scala, all operators are methods. Operators themselves are just syntactic sugar or a shorthand to call methods.
For example, let’s look at the arithmetic addition operator (+):
assert(1 + 2 == 3)
Here we use the symbol + as an operator to add two numbers. When we use the + symbol, internally Scala is invoking the method called +. We can also call the method + with the dot notation and it would give the same result:
assert(1.+(2) == 3)
Any method in Scala can be used as an operator. For example, the String.charAt() method, which returns a character at a given index can be invoked using the standard dot notation:
assert("Baeldung".charAt(0) == 'B')
It can also be invoked as an operator:
val char = "Baeldung" charAt 0
assert(char == 'B')
Both arithmetic addition (+) and String.charAt() are examples of infix operators. We can use infix notation to invoke any method that accepts at least one argument.
When a method accepts multiple parameters, we have to put all the parameters between a pair of parentheses to use the method in infix notation. For example, the String.replace() method takes two parameters:
assert("Baeldung".replace('g', 'G') == "BaeldunG")
We replaced all the small case g with the capital G. Using parentheses, we can call it in operator notation:
val str = "Baeldung" replace ('g', 'G')
assert(str == "BaeldunG")
2.1. Postfix and Prefix Operator Notation
So far, we saw examples of infix operator notation, which means the operator (or method) sits between two operands. There are two other types of operator notation – prefix and postfix.
Prefix operators appear before their operands. For example “–” in 10. All prefix operators are converted to methods with the name unary_<operator>:
assert(10.unary_ == 10)
Postfix operators appear after their operands. We can apply the String method toUpperCase as a postfix operator:
val strUpperCase = "baeldung" toUpperCase
assert(strUpperCase == "BAELDUNG")
As both prefix and postfix operators take just one argument, they are also called unary operators.
3. Basic Operators
All of Java’s basic operators work the same way in Scala, with some subtle differences. Let’s take a look at all basic types of Scala operators:
3.1. Arithmetic Operators
Scala has following arithmetic binary operators available for numeric types:
 Addition (+)
 Subtraction ()
 Multiplication (*)
 Division (/)
 Remainder (%)
We can use the infix operator notation to invoke them all:
assert(1 + 2 == 3)
assert(3.1  1.0 == 2.1)
assert(2 * 6 == 12)
assert(15 / 6 == 2)
assert(15 % 6 == 3)
Additionally, Scala also has two unary operators to indicate whether a number is positive or negative:
 + (method unary_+)
 – (method unary_)
+ makes a numeric literal positive and – makes a literal negative:
val num = 10
assert(num == 10)
assert(10 + num == 0)
The default value of a number literal is positive if no unary operator is specified.
3.2. Relational Operators
There are five relational operators in Scala:
 Greater than (>)
 Less than (<)
 Greater than or equal to (>=)
 Less than or equal to (<=)
All of the above relational operators evaluate to a Boolean:
assert(10 < 20 == true)
assert(10 > 20 == false)
assert(3.0 >= 2.5 == true)
assert(3.0 <= 2.5 == false)
Additionally, we also have a unary negate (!) operator to invert a Boolean:
assert(!true == false)
3.3. Logical Operators
Logical operators, logicalor ( and  ) and logicaland (&& and &) take Boolean operands and evaluate to a Boolean result. Logicalor evaluates to true only when either of the two operands is true. Logicaland evaluates to true only when both operands are true.
assert(true  false == true)
assert(true && false == false)
The && and  are shortcircuit operators. Expressions with these operators do not always evaluate both of its operands. The righthand side of the expression is ignored if the lefthand side determines the result alone.
For example, if the lefthand side of the expression with && is false, the expression does not need to evaluate the righthand side as it would always result in false. Similarly, if the lefthand side of  is true, the righthand side is not evaluated as the value would be true regardless.
Let’s see that in example for &&:
def printTrue() : Boolean = {
println("true");
true
}
def printFalse() : Boolean = {
println("false");
false
}
val result1 = printFalse() && printTrue() // only "false" is printed
assert(result1 == false)
val result2 = printTrue() && printFalse() // "true" and "false" are printed
assert(result2 == false)
In the first example, only the lefthand side is evaluated as it was enough to determine the result of the expression. As the printFalse method returns false, there’s no need to evaluate the righthand side.
In the second example, however, both sides of the expression are evaluated since the printTrue method returns true, and to determine the final result we have to know the value of the righthand side.
If we want to evaluate both sides of the expression, we can use & and  instead.
val result3 = printFalse() & printTrue() // "false" and "true" are printed
assert(result3 == false)
As we can see, & evaluates both sides of the expressions and does not shortcircuit.
3.4. Bitwise Operators
Bitwise operators perform operations on individual bits of integer data types. Scala has the following bitwise operators:
 Bitwiseor ()
 Bitwiseand (&)
 Bitwisexor (^)
 Unarybitwisecomplement (~)
Each performs the operation on the individual bits:
val bitwiseAndResult = 2 & 6
assert(bitwiseAndResult == 2)
& performs bitwiseand for each bit in 2 (0010) and 6 (0110), which evaluates to 2 (0010). Similarly,  and ^ perform bitwiseor and bitwisexor respectively.
~ inverts every bit, from true to false and viceversa:
assert(~2 == 3)
Scala also has three shift methods on integer data types:
 shiftleft (<<)
 shiftright (>>)
 unsignedshiftright (>>>)
All shift operators shift the integer value of the left operand by the amount specified by the value of the right operand. Shiftleft shifts bits to the left filling to the right with zeros:
assert(2 << 2 == 8)
Here we are shifting 2 (0010) twice to the left which yields, 8 (1000).
Both shiftright and unsignedshiftright shifts bits to the right. Shiftright fills with the highest bit of the lefthand value (signedbit) as it shifts while unsignedshiftright fills with zeros:
assert(8 >> 2 == 2)
8 in binary is 11111111111111111111111111111000. Here we are shifting bits to the right 2 times, filling up positions with the signed bit, which it being negative, is 1. Resulting in 2 (11111111111111111111111111111110).
assert(8 >>> 2 == 1073741822)
Unsignedshiftright, unlike shiftright, fills up bits with 0 as it shifts. Shifting left 8 (11111111111111111111111111111000) twice, yields 1073741822 (00111111111111111111111111111110).
3.5. Equality Operators
In Scala we use == to check for equality of two objects. != checks for inequality. Unlike Java, in Scala, you can use == to check equality for all objects, not just basic types.
4. Operator Precedence
When there are multiple operators present in an expression, they are evaluated based on operator precedence.
For example, 2+3*6 evaluates to 20 and not 30 because multiplication (*) operator has higher precedence than addition (+), so multiplication is carried out first.
Since Scala’s operators are just methods, the precedence is worked out by the priority of the first character of the method used in operator notation:
(all other special characters)
* / %
+ 
:
=!
< >
&
^

(all letters)
The higher the first character of a method in the above table the higher is the priority. If the first characters are at the same level then the order of evaluation is left to right:
assert(2 + 3 * 4 == 14)
Here the order of evaluation is 2 + (3 * 4), * is higher in precedence, resulting in 14.
assert(4  2 + 1 == 3)
Because + and – are at the same level in precedence, the order of evaluation is from left to right, that is (4 – 2) + 1.
There is one exception to the precedence rule. If the operator ends with the equals character (=), and its not one of the comparison operators (<=, =>, ==, !=), then the precedence is the same as of a simple assignment (=).
var num = 10
num += 2 * 10
assert(num == 30)
The order of evaluation is num += (2 * 10) as += has same precedence as = and is below multiplication (*).
5. Operator Associativity
When multiple operators with the same precedence appear in an expression the associativity determines how operators are grouped. The last character of a method determines associativity.
Methods that end with the “:” character are invoked by passing left operand to the one in right. Methods that end in any other character are opposite, the right operand is passed to the left operand:
assert(2 * 3 == 6)
Here the associativity is 2.*(3). Let’s see associativity for the List method :::,
assert(List(1,2) ::: List(3) == List(1, 2, 3))
In this case, the associativity changes and its evaluated as, List(3).:::(List(1,2)):
assert(List(3).:::(List(1,2)) == List(1, 2, 3))
6. Conclusion
In this article, we looked at how all operators in Scala are just methods. We went through all basic operators in Scala and learned about their precedence and associativity rules.
As always, all code examples can be found over on GitHub.