Why has !== lower precedence than === in Scala? - scala

Following code does not compile:
implicit class TripleEq(val x: Int) {
def === (y: Int) = x == y
def !== (y: Int) = x != y
}
val a = 0
val b = 1
if (a == a && b === b) {
println("Equal")
}
if (a != b && a !== b) {
println("Not equal")
}
The error is:
type mismatch;
found : Int
required: Boolean
The error goes away when I enclose the a !== b in parentheses.
I thought that operator precedence is defined by its first letter (see Tour of Scala) and therefore the precedence of !== should be the same as of ===, != or ==.
Why are parentheses required in the code above?

The answer is in the language specification of Assignment Operators:
There's one exception to this rule, which concerns assignment operators. The precedence of an assignment operator is the same as the one of simple assignment (=). That is, it is lower than the precedence of any other operator.
6.12.14 Assignment Operators
An assignment operator is an operator symbol (syntax category op in Identifiers) that ends in an equals character “=”, with the exception of operators for which one of the following conditions holds:
the operator also starts with an equals character, or
the operator is one of (<=), (>=), (!=).
Based on these rules !== is considered to be an assignment operator, while === is not.

Related

Identifier expected but integer literal found

I got this problem when writing a recursive function that calculates the number of points where two general functions f1 and f2 are equal(Assuming only Integer values).
object X1 {
def numEqual(f1:Int=>Int,f2:Int=>Int)(a:Int,b:Int):Int=
if(a>b) 0
else f1(a)==f2(a) ? 1+numEqual(f1,f2)(a+1,b):0+numEqual(f1,f2)(a+1,b)
And this is what compiler says :
X1.scala:5: error: identifier expected but integer literal found.
f1(a)==f2(a) ? 1+numEqual(f1,f2)(a+1,b) : 0+numEqual(f1,f2)(a+1,b)
^
one error found.
Thank you!
The if construct in Scala is an expression. As the others already said, there's no ternary operator because there's no need for it - the if being already an expression.
I rewrote your function to a tail-recursive version (to avoid StackOverflowErrors), let's see how it looks:
#tailrec def numEqual(f1: Int => Int, f2: Int => Int)(a: Int, b: Int, res: Int = 0): Int =
if (a > b) res
else {
val inc = if (f1(a) == f2(a)) 1 else 0
numEqual(f1, f2)(a + 1, b, res + inc)
}
Notice how the result of the if expression is assigned to inc - here you would normally use the ternary operator. Anyway, I hope this helps you.
the ? : operator doesn't exist in scala
Scala does not use the ternary operator, http://alvinalexander.com/scala/scala-ternary-operator-syntax

+= operator in Scala

I'm reading Programming in Scala by M. Odersky and now I'm trying to understand the meaning of operators. As far as I can see, any operator in Scala is just a method. Consider the following example:
class OperatorTest(var a : Int) {
def +(ot: OperatorTest): OperatorTest = {
val retVal = OperatorTest(0);
retVal.a = a + ot.a;
println("=")
return retVal;
}
}
object OperatorTest {
def apply(a: Int) = new OperatorTest(a);
}
I this case we have only + operator defined in this class. And if we type something like this:
var ot = OperatorTest(10);
var ot2 = OperatorTest(20);
ot += ot2;
println(ot.a);
then
=+
30
will be the output. So I'd assume that for each class (or type?) in Scala we have += operator defined for it, as a += b iff a = a + b. But since every operator is just a method, where the += operator defined? Maybe there is some class (like Object in Java) containing all the defenitions for such operators and so forth.
I looked at AnyRef in hoping to find, but couldn't.
+= and similar operators are desugared by the compiler in case there is a + defined and no += is defined. (Similarly works for other operators too.) Check the Scala Language Specification (6.12.4):
Assignment operators are treated specially in that they can be
expanded to assignments if no other interpretation is valid.
Let's consider an assignment operator such as += in an infix operation
l += r, where l, r are expressions. This operation can be
re-interpreted as an operation which corresponds to the assignment
l = l + r except that the operation's left-hand-side l is evaluated
only once.
The re-interpretation occurs if the following two conditions are
fulfilled.
The left-hand-side l does not have a member named +=, and also cannot
be converted by an implicit conversion to a value with a member named
+=. The assignment l = l + r is type-correct. In particular this implies that l refers to a variable or object that can be assigned to,
and that is convertible to a value with a member named +.

Precedence of the operators & and | in Scala

In the book "Programming in Scala" (Martin Odersky, 2nd edition) they give this operator precedence table (not complete here):
* / %
+ -
:
= !
< >
&
^
|
So that if the first character of an operator has a higher position in this table that the first character of another operator, the former operator is evaluated first.
According to that this code should print out yy, but it prints out x:
def x() = { print('x'); true }
def y() = { print('y'); true }
x || y && y // prints `x` but should `yy`
My understanding is that if & is higher in the table that |, it must be evaluated first. It is like * has precedence over +, so in x + y * y, the last statement is evalueted first.
EDIT:
Also look at this code
def x() = { print('x'); 1 }
def y() = { print('y'); 3 }
x == x + y * y // xxyy
Look like it evaluates them from left to right but "solves" them according to the table.
Raw version:
x || y && y
With precedence applied:
x || (y && y)
(Note, if the precedence was reversed it would be (x || y) && y.)
Now, you are expecting (y && y) to get evaluated before x, but Scala always evaluates left-to-right (see §6.6 of the language spec). And, as others have mentioned, || is a short-circuiting operator, so the the second operand is not even evaluated if the first operand returns true.
Another way to think of it is as a two method calls, where the second operand of both is pass-by-name:
or (x, and(y, y))
def or(a: Boolean, b: => Boolean): Boolean = if (a) true else b
def and(a: Boolean, b: => Boolean): Boolean = if (!a) false else b
Under the left-to-right evaluation model, x is ALWAYS evaluated first, then maybe y twice.
If you haven't already done so, you could follow Martin Odersky's functional programming course on Coursera where he talks about this very subject in lecture 1 or 2.
Your second example is equivalent to
add(x, mult(y, y))
def add(a: Int, b: Int) = a + b
def mult(a: Int, b: Int) = a * b
x is always evaluated first, then y, twice.
It prints x because x() call returns true and in case of || logic operator if left part return true, the right part is not computed. To compute it use | then, even if left part is true the right part will be evaluated
Updated
Example with boolean is not good, because in case with booleans so called "short-circuit" evaluation is used and scalac won't even look at the second part of or expression if the left part is true. Think of this operation like:
def || (a: => Boolean) = ???

Type mismatch with If statement containing bitwise operators

I am new to scala but I am having the problem with the following code:
var c:Int = 0
var j:Int = 0
for( c <- 0 to 100){
for( j <- 0 to 100){
/* Check if jth bit in c is set,
if( (c & (1<<j)) ) // this line is the line where i get the error
xs :+ (ys(j)) // this is copying element j from list ys to list xs
}
}
The error I get is:
type mismatch; found : Int required: Boolean
the code (c & (1<<j)) should be shifting 1 left j bits and then bitwise anding the result to the int in the variable c to get a boolean result.
It is entirely possible that I am doing something wrong.. I have been learning Scala fro 3 days and I am very rusty on my java.
Any help would be appreicated
Bitwise operations in Scala (in fact in any language) return a result of type Int, your if expression requires a type of Boolean. Scala doesn't treat Boolean values like C, where you code would work fine.
You can make your expression return a Boolean by testing explicitly for 1:
if((c & (1 << j)) != 0)
Unlike in C (or C++), Scala's if statement (just like Java) only accepts a Boolean expression, and there is no implicit type promotion from integral types to Boolean. So you need to be explicit about what you want, and replace if( (c & (1<<j)) ) with if( (c & (1<<j)) != 0)

&& and || in Scala

since normal operators like +, ::, -> and so on are all methods which can be overloaded and stuff I was wondering if || and && are methods as well. This could theoretically work if this were methods in of the boolean object.
But if they are, why is something like
if (foo == bar && buz == fol)
possible? If the compiler reads from right to left this would invoke && on bar instead of (foo == bar)
6.12.3 Infix Operations An infix operator can be an arbitrary
identifier. Infix operators have
precedence and associativity defined
as follows:
The precedence of an infix
operator is determined by the
operator’s first character. Characters
are listed below in increasing order
of precedence, with characters on the
same line having the same precedence.
(all letters)
|
^
&
< >
= !
:
+ -
* / %
(all other special characters)
That is, operators starting with a
letter have lowest precedence,
followed by operators starting with
‘|’, etc.
There’s one exception to
this rule, which concerns assignment
operators(§6.12.4). The precedence of
an assigment operator is the same as
the one of simple assignment (=). That
is, it is lower than the precedence of
any other operator.
It follows with an explanation of associativity, and how it all combines in a expression with multiple operators. The Scala Reference makes good reading.
Because method starts with = has a higher precedence than method starts with &.
So (foo == bar && buz == fol) will become something like the following:
val tmp1: Boolean = (foo == bar)
val tmp2: Boolean = (buz == fol)
tmp1 && tmp2
Those two are definitely methods in scala.