If Statement Scala behaving Strangely - scala

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.

Related

Scala coding standards: curly braces on the same line

The scala coding standards state that
Technically, Scala’s parser does support GNU-style notation with opening braces on the line following the declaration. However, the parser is not terribly predictable when dealing with this style due to the way in which semi-colon inference is implemented. Many headaches will be saved by simply following the curly brace convention demonstrated above.
I've looked, and I couldn't find any real examples of this. Can anyone explain the reasoning behind this with an exmaple? Has anyone run into problems with using curly braces on a new line?
Consider this expression:
someElement
{
// Some code
}
How is this interpreted? Is it an expression (such as a value, or a function call with no arguments) followed by a block statement enclosed within braces? Or is it a function call with the braces enclosing a single argument?
If Scala didn't have semicolon inference—that is, if Scala required semicolons to denote the end of a statement in the same manner that Java does—then the two could be easily distinguished because the former would require a semicolon at the end of the first line. However, the Scala parser has to infer where the semicolon(s) need to be to make sense of the code, and sometimes it gets things wrong. (Both interpretations, depending upon context, are valid and it's not always possible for the Scala parser to resolve the ambiguity by itself.)
For example, let's say that someElement is a function with a by name argument. If you attempt to call it in the Scala REPL intending to put the argument (within braces) on another line, you'll find that entering someElement alone causes an error:
> scala
Welcome to Scala 2.12.4 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_161).
Type in expressions for evaluation. Or try :help.
scala> def someElement(x: => Int): Int = {
| // Do something...
| x
| }
someElement: (x: => Int)Int
scala> someElement
<console>:13: error: missing argument list for method someElement
Unapplied methods are only converted to functions when a function type is expected.
You can make this conversion explicit by writing `someElement _` or `someElement(_)` instead of `someElement`.
someElement
^
That is, you don't even get as far as entering the braces. However, if you enter the following, then you're OK:
scala> someElement {
| 10
| }
res0: Int = 10
But what if someElement is a value? Now we see this in the REPL:
scala> val someElement = 5
someElement: Int = 5
scala> someElement
res1: Int = 5
scala> {
| 5
| }
res2: Int = 5
Now the REPL accepts the same code, on separate lines, as two different expressions.
Let's get really ambiguous. Say someElement is a value, but it's now a reference to a function taking a single argument. Let's look at the possible interpretations:
scala> def square(a: Int) = a * a
square: (a: Int)Int
scala> val someElement = square _
someElement: Int => Int = $$Lambda$1034/1609754699#74abbb
scala> someElement
res3: Int => Int = $$Lambda$1034/1609754699#74abbb
scala> {
| 5
| }
res4: Int = 5
That is, it's treated as two separate statements: a value followed by a block statement. However:
scala> someElement {
| 5
| }
res5: Int = 25
is treated as a call to square with an argument of 5.
The Scala compiler is a little smarter than the REPL since it can see all of the code at once, and will try to resolve ambiguities by seeing which of the alternatives make the most sense, but its interpretation may not always match yours.
So, as you can see, putting the open brace on the same line—if the two expressions are linked—makes the relationship explicit and removes ambiguity. Alternatively, if you want the expressions to be parsed unambiguously as separate statements, add a semicolon after the first line.
(IMHO, the semicolon inference is one of Scala's Achilles Heels.)

How does scala infers the type of a variable?

I am always fascinated to see how scala always infers the type correctly . How scala does it?
scala> val num = 5
num: Int = 5
scala> val num = "5"
num: String = 5
I know it might be a very stupid question to ask here but i don't know the answer.
Please enlighten me.
Thanks!
There are several methods for inferencing the type of a variable. Mainly using those called inference rules based in logic theory.
There are plenty of papers explaining the theory behind. Here I put a good example (with Scala ;) )
www2.in.tum.de/hp/file?fid=879
While parsing the code compile can infer that 5 is of type Int and "5" is of String type.
In simple terms any value enclosed in double quotes " will be considered String, value enclosed in single quote ' is considered Char and digits are considered Int (unless specified otherwise).
This is further used to used to infer types for expression results.
Consider this example
val a = 5 // translates to val a:Int = 5
val b = "5" // translates to val b:String = "5"
val x = a+1 // expression 1
val y = b+1 // expression 2
In this example the code type of a is inferred as Int and type of b is inferred as String.
Based on this expression 1 calls function Int.+(x: Int): Int which returns Int, hence type of x is guessed to be Int.
Similarly expression 2 calls function StringOps.+(arg0: Any): String which returns String, hence type of y is guessed to be String.

Getting an error while passing an expression as a fucntion parameter

scala> def sum(a:Int)={a} //I have defined the function with a single parameter
sum: (a: Int)Int
sum{val b=10+20} //passing the parameter as expression block
Getting error
scala> sum{val b=10+20}
<console>:9: error: type mismatch;
found : Unit
required: Int
sum{val b=10+20}
Why is it expecting Unit here?
The error is that {val b = 10 + 20} is of type Unit while sum is expecting an Int.
You can either call sum directly without assigning the variable:
sum(10 + 20)
> 30
Or make the block return an Int, like:
sum{
val b = 10 + 20
b // return b, which is an Int
}
> 30
You do not pass an expression but a block with one declaration. Try:
sum(10+20)
You are experiencing a weird combination of syntax error and type-system convention.
The curly braces mark a block (see e.g. the body of your sum function declaration). Function arguments can be passed in juxtaposition or using parenthesis. That is your syntax error.
The type system convention allows languages with side-effects to gently insert these effects into basically any expression. This happens by treating the composition of statements (i.e. the semicolon) as "evaluate these expression but do nothing with the result, then evaluate the next expression". The nothing as result part is combined with the unit type for statements that do not compute anything.
def sum(a:Int)={a}
What this statement does is create a method that takes one Int-typed parameter and returns it.
sum{val b=10+20}
Here you pass a value to your defined method sum. What you're passing is an expression. Scala will, effectively, 'rewrite' that expression before applying it to sum. If we write the expression being passed (val b=10+20) in the REPL we will see what it gets rewritten to:
scala> val b=10+20
b: Int = 30
But this is only part of the story, because the assignment of a value to a name returns nothing. We can see this by putting brackets around the assignment:
scala> { val b=10+20 }
Note that the REPL displays nothing when this happens.
Because the re-written expression includes this evaluation, you're actually passing a scope to the function, in which b is defined. However, that scope doesn't 'return' an Int to be bound to a. To return the result of the b assignment, you have to do one of two things. Either you have to have a call to the variable be the last call in the expression, or have the last call be the calculation itself, and don't assign that to a variable:
sum{ val b=10+20; b } // Explicitly call the bound variable
sum{ 10 + 20 } // Don't assign the variable

How to annotate types of expressions within a Scala for expression

I'm wondering how to (safely) add type ascriptions to the lefthand side of Scala for expressions.
When working with complex for expressions, the inferred types are often hard to follow, or can go off track, and it's desirable to annotate the expressions within the for {..} block, to check that you and the compiler agree. An illustrative code sketch that uses the Eff monad:
for {
e1: Option[(Int, Vector[Int])] <- complexCalc
e2 <- process(e1)
} yield e2
def complexCalc[E]: Eff[E, Option[(Int, Vector[Int])]] = ???
However, this conflicts with Scala's support for pattern matching on the LHS of a for-expression.
As discussed in an earlier question, Scala treats the type ascription : Option[(Int, Vector[Int])] as a pattern to be matched.
The compiler has the concept of irrefutable patterns, which always match. Conversely, a refutable pattern might not match, and so when used in for expression, the righthand-side expression must provide a withFilter method to handle the non-matching case.
Due to a longstanding compiler bug/limitation, tuples and other common constructor patterns seem never to be treated as irrefutable.
The net result is that adding a type ascription makes the LHS pattern seem refutable and requires a filter op to be defined on the RHS. A symptom is compiler errors like value filter is not a member of org.atnos.eff.Eff[E,Option[(Int, Vector[Int])]].
If there any syntactic form that can be used to ascribe types to the intermediate expressions containing tuples, within for expressions, without encountering refutable pattern matching?
Turns out there's extensive discussion of this problem, and the current best solution, in this Scalaz PR *.
The work around is to add the type ascription in an assignment on the line below:
for {
e <- complexCalc
e1: Option[(Int, Vector[Int])] = e
e2 <- process(e1)
} yield e2
def complexCalc[E]: Eff[E, Option[(Int, Vector[Int])]] = ???

"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.