&& and || in Scala - 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.

Related

Spark Scala compiler not complaining about double vs. triple equals

I get a compiler error if I try this
df.filter($"foo" == lit(0))
forgetting that I need a triple equals in Spark.
However, if I do this, I get the wrong answer but no error:
df.filter($"foo".between(baz, quux) || $"foo" == lit(0))
Can someone explain why compile-time checks help me in the first case, but not the second?
Because $"foo" == lit(0) is always evaluated as Boolean = false.
So in the first case, you trying to call method filter by passing a Boolean whereas it expects a string expression or column expression. Thus you get an error.
Now in the second, case:
$"foo".between(baz, quux) || $"foo" == lit(0) is evaluated as:
(((foo >= baz) AND (foo <= quux)) OR false)
which is accepted beacause you doing an OR || between a column expression ($"foo".between(baz, quux)) and a literal boolean false.
In other words, it is interpreted as $"foo".between(baz, quux) || lit(false)

Why has !== lower precedence than === in 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.

Haskell own instance typeclass

I need to declare my own typeclass but I dont understand why there is the (==).
data Egg = Soft | Hard
instance Eq Egg where
(==)
I did not find anything where the (==) is used in an instance, only in a class
The easy way to have an instance of Eq is:
data Egg = Soft | Hard deriving Eq
The hard way (with more control):
data Egg = Soft | Hard
instance Eq Egg where
Soft == Soft = True
Hard == Hard = True
_ == _ = False
UPD: Since the equality function (==) as an operator seem to be the confusing bit, here is the same instance written with a prefix notation:
data Egg = Soft | Hard
instance Eq Egg where
(==) Soft Soft = True
(==) Hard Hard = True
(==) _ _ = False
As a quick reminder: operator are infix (in between terms) by default, and functions are prefix (before terms) by default. To make an operator prefix it is surrounded by (), to make a function infix it is surrounded by ``. Here is a thread talking about which characters are used for operator vs functions.
I assume you’re trying to make an instance of the standard typeclass Eq for your custom datatype. The Eq class is defined as:
class Eq a where
(==) :: a -> a -> Bool
a == b = not (a /= b)
(/=) :: a -> a -> Bool
a /= b = not (a == b)
That is, it defines two methods == and /= (which happen to be operators), and provides default implementations of each one in terms of the other. So to make an instance of Eq for your own type, you need to provide an implementation of one or both of these functions (== or /=) for your type. Note that the body of the instance must be indented.
instance Eq Egg where
Soft == Soft = True
Hard == Hard = True
_ == _ = False
Just as you can use a Haskell operator in prefix form by wrapping it in parentheses, e.g., (==) 1 1, you can also implement an operator definition in prefix form:
instance Eq Egg where
(==) Soft Soft = True
(==) Hard Hard = True
(==) _ _ = False
You could even use a case if you so desired:
instance Eq Egg where
(==) a b = case (a, b) of
(Soft, Soft) -> True
(Hard, Hard) -> True
_ -> False
Note that these are all the same as the instance that would be generated for you automatically with deriving:
data Egg = Soft | Hard
deriving (Eq)

When to use parenthesis in Scala infix notation

When programming in Scala, I do more and more functional stuff. However, when using infix notation it is hard to tell when you need parenthesis and when you don't.
For example the following piece of code:
def caesar(k:Int)(c:Char) = c match {
case c if c isLower => ('a'+((c-'a'+k)%26)).toChar
case c if c isUpper => ('A'+((c-'A'+k)%26)).toChar
case _ => c
}
def encrypt(file:String,k:Int) = (fromFile(file) mkString) map caesar(k)_
The (fromFile(file) mkString) needs parenthesis in order to compile. When removed I get the following error:
Caesar.scala:24: error: not found: value map
def encrypt(file:String,k:Int) = fromFile(file) mkString map caesar(k)_
^
one error found
mkString obviously returns a string on which (by implicit conversion AFAIK)I can use the map function.
Why does this particular case needs parentheses? Is there a general guideline on when and why you need it?
This is what I put together for myself after reading the spec:
Any method which takes a single parameter can be used as an infix operator: a.m(b) can be written a m b.
Any method which does not require a parameter can be used as a postfix operator: a.m can be written a m.
For instance a.##(b) can be written a ## b and a.! can be written a!
Postfix operators have lower precedence than infix operators, so foo bar baz means foo.bar(baz) while foo bar baz bam means (foo.bar(baz)).bam and foo bar baz bam bim means (foo.bar(baz)).bam(bim).
Also given a parameterless method m of object a, a.m.m is valid but a m m is not as it would parse as exp1 op exp2.
Because there is a version of mkString that takes a single parameter it will be seen as an infix opertor in fromFile(file) mkString map caesar(k)_. There is also a version of mkString that takes no parameter which can be used a as postfix operator:
scala> List(1,2) mkString
res1: String = 12
scala> List(1,2) mkString "a"
res2: String = 1a2
Sometime by adding dot in the right location, you can get the precedence you need, e.g. fromFile(file).mkString map { }
And all that precedence thing happens before typing and other phases, so even though list mkString map function makes no sense as list.mkString(map).function, this is how it will be parsed.
The Scala reference mentions (6.12.3: Prefix, Infix, and Postfix Operations)
In a sequence of consecutive type infix operations t0 op1 t1 op2 . . .opn tn, all operators op1, . . . , opn must have the same associativity.
If they are all left-associative, the sequence is interpreted as (. . . (t0 op1 t1) op2 . . .) opn tn.
In your case, 'map' isn't a term for the operator 'mkstring', so you need grouping (with the parenthesis around 'fromFile(file) mkString')
Actually, Matt R comments:
It's not really an associativity issue, more that "Postfix operators always have lower precedence than infix operators. E.g. e1 op1 e2 op2 is always equivalent to (e1 op1 e2) op2". (Also from 6.12.3)
huynhjl's answer (upvoted) gives more details, and Mark Bush's answer (also upvoted) point to "A Tour of Scala: Operators" to illustrate that "Any method which takes a single parameter can be used as an infix operator".
Here's a simple rule: never used postfix operators. If you do, put the whole expression ending with the postfix operator inside parenthesis.
In fact, starting with Scala 2.10.0, doing that will generate a warning by default.
For good measure, you might want to move the postfix operator out, and use dot notation for it. For example:
(fromFile(file)).mkString map caesar(k)_
Or, even more simply,
fromFile(file).mkString map caesar(k)_
On the other hand, pay attention to the methods where you can supply an empty parenthesis to turn them into infix:
fromFile(file) mkString () map caesar(k)_
The spec doesn't make it clear, but my experience and experimentation has shown that the Scala compiler will always try to treat method calls using infix notation as infix operators. Even though your use of mkString is postfix, the compiler tries to interpret it as infix and so is trying to interpret "map" as its argument. All uses of postfix operators must either be immediately followed by an expression terminator or be used with "dot" notation for the compiler to see it as such.
You can get a hint of this (although it's not spelled out) in A Tour of Scala: Operators.

Why do people use _? as an identifier suffix?

I start reading Lift framework source code, I find that there're so many methods are defined using a name like methodName_? , is there a convention that _? has some special meaning?
def empty_? : Boolean = {}
You're unlikely to see the construct outside of the lift framework; I suspect that it's mostly Ruby-envy.
Almost any other Scala project will shy away from this syntax. Not because of the trailing question mark, but because it's yet another way to introduce underscores into your code - and the symbol is already far too heavily overloaded.
Based on an evaluation of multiple Scala projects, the notation can be reasonably described as non-idiomatic.
UPDATE
The reason that the underscore is required is to disambiguate from infix notation, in which:
x?y
would be read as
x.?(y)
with ? being a method name. Whereas:
x_?y
Clearly demarks x_? as being atomic.
The syntax is an example of what is formally known as a "mixed identifier", and is intended to allow definitions such as
def prop_=(v:String) = ... //setter
def unary_- = ... //prefix negation operator
It could (arguably) be considered a hack when similar construct is used simply to shove a question mark at the end of a method name.
The ? denotes that this is a predicate, a function returning Boolean. This convention goes back to Lisp, where ? (Scheme), p or -p (other Lisps, simulating the question mark with a "similar" letter) also denote predicates. Think of it as asking a question, "is the object empty?"
Scala will only allow mixed identifier names (containing alphanumerics and punctuation) if you separate them by _. E.g.,
scala> def iszero?(x : Int) = x == 0
<console>:1: error: '=' expected but identifier found.
def iszero?(x : Int) = x == 0
^
doesn't work, but
scala> def iszero_?(x : Int) = x == 0
iszero_$qmark: (x: Int)Boolean
does.