Skip to content

Add code tabs for _tour/operators #2561

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Oct 4, 2022
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 63 additions & 0 deletions _tour/operators.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,17 +11,30 @@ prerequisite-knowledge: case-classes
redirect_from: "/tutorials/tour/operators.html"
---
In Scala, operators are methods. Any method with a single parameter can be used as an _infix operator_. For example, `+` can be called with dot-notation:

{% tabs operators_1 %}
{% tab 'Scala 2 and 3' for=operators_1 %}
```
10.+(1)
```
{% endtab %}
{% endtabs %}

However, it's easier to read as an infix operator:

{% tabs operators_2 %}
{% tab 'Scala 2 and 3' for=operators_2 %}
```
10 + 1
```
{% endtab %}
{% endtabs %}

## Defining and using operators
You can use any legal identifier as an operator. This includes a name like `add` or a symbol(s) like `+`.

{% tabs operators_3 class=tabs-scala-version %}
{% tab 'Scala 2' for=operators_3 %}
```scala mdoc
case class Vec(x: Double, y: Double) {
def +(that: Vec) = Vec(this.x + that.x, this.y + that.y)
Expand All @@ -34,27 +47,62 @@ val vector3 = vector1 + vector2
vector3.x // 3.0
vector3.y // 3.0
```
{% endtab %}
{% tab 'Scala 3' for=operators_3 %}
```scala
case class Vec(x: Double, y: Double):
def +(that: Vec) = Vec(this.x + that.x, this.y + that.y)

val vector1 = Vec(1.0, 1.0)
val vector2 = Vec(2.0, 2.0)

val vector3 = vector1 + vector2
vector3.x // 3.0
vector3.y // 3.0
```
{% endtab %}
{% endtabs %}

The class Vec has a method `+` which we used to add `vector1` and `vector2`. Using parentheses, you can build up complex expressions with readable syntax. Here is the definition of class `MyBool` which includes methods `and` and `or`:

{% tabs operators_4 class=tabs-scala-version %}
{% tab 'Scala 2' for=operators_4 %}
```scala mdoc
case class MyBool(x: Boolean) {
def and(that: MyBool): MyBool = if (x) that else this
def or(that: MyBool): MyBool = if (x) this else that
def negate: MyBool = MyBool(!x)
}
```
{% endtab %}
{% tab 'Scala 3' for=operators_4 %}
```scala
case class MyBool(x: Boolean):
def and(that: MyBool): MyBool = if x then that else this
def or(that: MyBool): MyBool = if x then this else that
def negate: MyBool = MyBool(!x)
```
{% endtab %}
{% endtabs %}

It is now possible to use `and` and `or` as infix operators:

{% tabs operators_5 %}
{% tab 'Scala 2 and 3' for=operators_5 %}
```scala mdoc
def not(x: MyBool) = x.negate
def xor(x: MyBool, y: MyBool) = (x or y) and not(x and y)
```
{% endtab %}
{% endtabs %}

This helps to make the definition of `xor` more readable.

## Precedence
When an expression uses multiple operators, the operators are evaluated based on the priority of the first character:

{% tabs operators_6 %}
{% tab 'Scala 2 and 3' for=operators_6 %}
```
(characters not shown below)
* / %
Expand All @@ -67,12 +115,27 @@ When an expression uses multiple operators, the operators are evaluated based on
|
(all letters, $, _)
```
{% endtab %}
{% endtabs %}

This applies to functions you define. For example, the following expression:

{% tabs operators_7 %}
{% tab 'Scala 2 and 3' for=operators_7 %}
```
a + b ^? c ?^ d less a ==> b | c
```
{% endtab %}
{% endtabs %}

Is equivalent to

{% tabs operators_8 %}
{% tab 'Scala 2 and 3' for=operators_8 %}
```
((a + b) ^? (c ?^ d)) less ((a ==> b) | c)
```
{% endtab %}
{% endtabs %}

`?^` has the highest precedence because it starts with the character `?`. `+` has the second highest precedence, followed by `==>`, `^?`, `|`, and `less`.