Adding an Int to a String in scala [duplicate] - scala

This question already has answers here:
Scala operator oddity
(2 answers)
Closed 10 years ago.
I am having a little trouble understanding the rationale behind the following few pieces of scala code:
We all know that 1 + 1 = 2 in the REPL.
scala> 1 + 1
res0: Int = 2
If I type in "Abc" + "Def", I should get "AbcDef" in the REPL.
scala> "Abc" + "Def"
res6: java.lang.String = AbcDef
Now let's say I invoke the + method on String "Abc" and pass "Def" as a parameter:
scala> "Abc".+("Def")
res7: java.lang.String = AbcDef
By the same rationale, why does something like 1.+(1) return a double 2.0?
scala> 1.+(1)
res1: Double = 2.0
Also, why does passing the argument "1" as a parameter result in "1.01" as follows:
scala> 1.+("1")
res9: String = 1.01
Why is the returned result a String instead of an effort for "1" to me transformed into the callers type?
Thanks

If you try that on Scala 2.10.0, you'll get a clue as to the answer:
scala> 1.+(1)
<console>:1: warning: This lexical syntax is deprecated. From scala 2.11,
a dot will only be considered part of a number if it is immediately
followed by a digit.
1.+(1)
^
Simply put, 1. is a valid Double in Scala (as it is in Java), so Scala is really doing this:
1. + (1)
That is, infix addition of a Double to an expression enclosed inside a (redundant) parenthesis.
As for the latter, Scala follows Java convention that anything added to a String results in a String and vice versa.

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.

Type mismatch when using + operator

I'm currently trying to learn how to use Scala but I'm stuck with some syntax problems.
When I type in the scala prompt:
import scala.collection.immutable._
var q = Queue[Int](1)
println((q+1).toString)
I get the following error:
<console>:12: error: type mismatch;
found : Int(1)
required: String
println((q+1).toString)
I just wanted to use the overloaded + operator of the queue defined as below:
def +[B >: A](elem : B) : Queue[B]
Creates a new queue with element added at the end of the old queue.
Parameters
elem - the element to insert
But it seems that scala does a string concatenation. So, can you help me to understand how to add an element to the queue (without using enqueue which works perfectly; I would like to use the + operator)? And maybe, could you give me some explaination about that behaviour that seems a bit strange for a beginner?
Thank you
You are using the wrong operator (see docs):
scala> var q = Queue[Int](1)
q: scala.collection.immutable.Queue[Int] = Queue(1)
scala> q :+ 2
res1: scala.collection.immutable.Queue[Int] = Queue(1, 2)
scala> 0 +: q
res2: scala.collection.immutable.Queue[Int] = Queue(0, 1)
Since the + operator has no other meaning given those types, Scala defaults to String concatenation, giving you the type mismatch error.

How can I find the definition of methods/operations defined in an implicitly-converted class?

I'm looking at someone else's source code (Scala), where I see the operator :+= being called on a variable of type IndexedSeq. I am looking all over the scaladocs page for that class to figure out what that operator does, but I do not see it. I'm thinking that either it's defined in a class outside of IndexedSeq's inheritance hierarchy, or else the javascript on the scaladocs page is hiding it somewhere I can't see it. (Actually it's neither; see answer below.)
I've hit every button on the scaladocs page trying to unhide everything. I've looked in the web-page's HTML code. There has got to be a way to look up an operator from the documentation of a class to which it can be applied. Hasn't there?
(N.B.: I looked up that operator using symbolhound, so I know what that operator means now. This question is about scala documentation in general, not that particular operator.)
All operators in Scala are normal methods.
You cannot find it because it is compiler magic for re-assignement, it is not an operator. Or to say it another way: it looks like an operator of its own, but it is actually "an operator followed by the = character".
The compiler will magically turn that into a assignment if the operator (here :+) returns the proper type, and the original value was a var, obviously.
Since it is not provided by any implicit nor explicit method on Seq[T] or whatever, it does not appear anywhere in the generated scaladoc.
So to answer the general question:
It is a language construct, so the only place where it is documented is the specification, sadly,
but, if you find some "<?>=" unknown operator somewhere, look for the definition of "<?>", that one is sure to be documented.
Edit: I finally found where this is defined in the SLS:
§6.12.4:
An assignment operator is an operator symbol (syntax category op in (§1.1)) that
ends in an equals character “=”, with the exception of operators for which one of the
following conditions holds:
(1) the operator also starts with an equals character, or
(2) the operator is one of (<=), (>=), (!=).
It also says later on that it only happens when all other options have been tried (including potential implicits).
Is this value assigned to a variable? If it's the case I think this syntax sugar:
scala> var x = IndexedSeq(1,2,3)
x: IndexedSeq[Int] = Vector(1, 2, 3)
scala> x :+= 10
scala> x
res59: IndexedSeq[Int] = Vector(1, 2, 3, 10)
scala> val y = IndexedSeq(1,2,3)
y: IndexedSeq[Int] = Vector(1, 2, 3)
scala> y :+= 10
<console>:16: error: value :+= is not a member of IndexedSeq[Int]
y :+= 10
^
It is syntax sugar for "operation and assignment", like +=:
scala> var x = 10
x: Int = 10
scala> x += 1
scala> x
res63: Int = 11
Which de-sugars to x = x + 1.

Scala operator oddity

When I invoke + on 2 I get an Int back, but when its done using explicit method call I get Double instead.
scala> 2+2
res1: Int = 4
scala> 2.+(2)
res2: Double = 4.0
It seems that .+() is invoked on implicit converted Int to Double.
scala> 2.+
<console>:16: error: ambiguous reference to overloaded definition,
both method + in class Double of type (x: Char)Double
and method + in class Double of type (x: Short)Double
match expected type ?
2.+
^
Why is that so ?
In Scala 2.9 and before, 2. is interpreted as 2.0 so the ambiguous dot denotes a float literal. You’d explicitly call the method by using the syntax (2).+(2).
The ambiguous floating point syntax will however be deprecated in 2.10:
scala> 2.+(2)
<console>:1: warning: This lexical syntax is deprecated. From scala 2.11, a dot will only be considered part of a number if it is immediately followed by a digit.
2.+(2)
^
<console>:2: warning: This lexical syntax is deprecated. From scala 2.11, a dot will only be considered part of a number if it is immediately followed by a digit.
2.+(2)
^
<console>:8: warning: This lexical syntax is deprecated. From scala 2.11, a dot will only be considered part of a number if it is immediately followed by a digit.
2.+(2)
^
res1: Double = 4.0
The reason is not in explicit method call -- by writing 2.+ you specifying Double on the left side and then calling addition operator on it:
scala> 2.
res0: Double = 2.0