Operators, Precedence and Type - rohgar/scala-principles-1 GitHub Wiki
Consider the class:
class Rational(x: Int, y: Int) {
require(y != 0)
def numer = x
def numer = y
def add(that: Rational) = ...
def subtract(that: Rational) = ...
}
In principle, the rational numbers defined by Rational are as natural as integers. But for the user of these abstractions, there is a noticeable difference:
- We write
x + y
, if x and y are integers, but - We write
r.add(s)
if r and s are Rational instances. In Scala, we can eliminate this difference. We proceed in two steps.
It is possible to write
r add s r.add(s)
r less s /* in place of */ r.less(s)
r max s r.max(s)
Operators hence, can be used as Identifiers (method identifiers) which are either Alphanumeric (must start with a letter) or Symbolic, ( an _ counts as a letter).
Eg. x1
, *
, +?%&
, vector_++
, counter_=
.
Using these, the above class Rational can be re-written:
class Rational(x: Int, y: Int) {
require(y != 0)
def numer = x / g
def denom = y / g
def + (that: Rational) = ...
def - (that: Rational) = ...
...
}
This can be used as below:
val x = new Rational(1, 2)
val y = new Rational(1, 3)
val p = x + y // instead of x.add(y)
Note: To define prefix operators like -x
, we have to define them as unary_-
.
Eg.
class Rational(x: Int, y: Int) {
require(y != 0)
def numer = x / g
def denom = y / g
def unary_- : Rational = new Rational(-numer, denom) //note the space between - and :
}
// Then we can use:
val x = new Rational(1, 2)
val p = -x // i.e. -1/2
The following table lists the characters in increasing order of priority precedence:
(all letters)
|
^
&
< >
= !
:
+ -
* / %
(all other special characters)
We can define a type in Scala using the type
keyword:
class Foo {
type T = Int
def method: T = 42 // A method which returns an Int 42
}
A function can also be used as a type.
// Set is a function which takes in an integer and returns a Boolean
type Set = Int => Boolean