sml code 3>4 orelse 5<6 andalso not 7<>8; - smlnj

3>4 orelse 5<6 andalso not 7<>8;
Please why is the above sml generating error as follow
3>4 orelse 5<6 andalso not 7<>8;
stdIn:1.25-1.33 Error: operator and operand don't agree [overload conflict]
operator domain: bool
operand: [int ty]
in expression:
not 7

Your expressions is parsed as the following, because function application has higher precedence than any other binary operator:
3>4 orelse 5<6 andalso (not 7)<>8
Note the (not 7) part, which doesn't make sense. So, you have to explicitly say what's the argument to not:
3>4 orelse 5<6 andalso not (7<>8)

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)

If Statement Scala behaving Strangely

if statment in scala is behaving strangely
scala> val a = 10
a: Int = 10
scala> if (a > 10) 1
res10: AnyVal = ()
scala> if (a <= 10) 1
res12: AnyVal = 1
Why didn't we get return type as Int? Why we got AnyVal
if statment in scala is behaving strangely
Scala doesn't have an if statement. In fact, Scala has no statements at all. Scala has an if expression, or more precisely, a conditional expression.
In fact, if Scala had an if statement, then your question wouldn't make sense, because statements have no value and thus no type.
Why didn't we get return type as Int? Why we got AnyVal
As the documentation says:
The conditional expression if (e1) e2 else e3 chooses one of the values of e2 and e3, depending on the value of e1. […] The type of the conditional expression is the weak least upper bound of the types of e2 and e3.
This makes sense: the conditional can be either true or false, so the value of the conditional expression is either the "then" part or the else part. Since the value can be either the "then" part or the else part, the type of the expression obviously must be compatible with both.
In your case, the value of the "then" part is 1 whose type is Int and the value of the else part is () whose type is Unit:
A short form of the conditional expression eliminates the else-part. The conditional expression if (e1) e2 is evaluated as if it was if (e1) e2 else ().
Therefore, whatever the type of the whole expression is, it must be compatible with both Int and Unit. And the most-precise possible type that is compatible with both Int and Unit is AnyVal:[Source: Scala 2.13 Language Specification – Section 12 The Scala Standard Library]
As you can see in the left half of the tree, the weak-LUB of Int and Unit is obviously AnyVal.

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.

"true && E" returns "E" in Scala?

In the course on Scala at Coursera (lecture 1.4, around 3 mins), Martin Odersky says that the expression true && e always returns e (e is any object). And the expression false || e also returns e. He explains that sometimes the last expression is not always evaluated.
But when I run these expressions I get error: type mismatch.
For true && 5 I get found: Int(5); required: Boolean
Has Scala evolved in recent times or what am I doing wrong?
e stands for boolean expression.
Predicate: a boolean expression to be evaluated e.g. (x >= 4), (x != 0), etc
see https://sites.google.com/a/stonybrook.edu/functional-programming-scala/lecture-1-4
From the Scala Reference book, paragraph 6.16 Conditional expressions, given:
if (e1) e2 else e3
The condition e1 is expected to conform to type Boolean. The then-part
e2 and the else-part e3 are both expected to conform to the expected
type of the conditional expression. The type of the conditional
expression is the weak least upper bound (§3.5.3) of the types of e2
and e3.

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.