What is the differences between Int and Integer in Scala? - scala

I was working with a variable that I had declared as an Integer and discovered that > is not a member of Integer. Here's a simple example:
scala> i
warning: there were deprecation warnings; re-run with -deprecation for details
res28: Integer = 3
scala> i > 3
<console>:6: error: value > is not a member of Integer
i > 3
^
Compare that to an Int:
scala> j
res30: Int = 3
scala> j > 3
res31: Boolean = false
What are the differences between Integer and Int? I see the deprecation warning but it's unclear to me why it was deprecated and, given that it has been, why it doesn't have a > method.

"What are the differences between Integer and Int?"
Integer is just an alias for java.lang.Integer. Int is the Scala integer with the extra capabilities.
Looking in Predef.scala you can see this the alias:
/** #deprecated use <code>java.lang.Integer</code> instead */
#deprecated type Integer = java.lang.Integer
However, there is an implicit conversion from Int to java.lang.Integer if you need it, meaning that you can use Int in methods that take an Integer.
As to why it is deprecated, I can only presume it was to avoid any confusion over which kind of integer you were working with.

Integer gets imported from java.lang.Integer and is only for compatibility with Java. Since it is a Java class, of course it can't have a method called "<".
EDIT: You can mitigate this problem by declaring an implicit conversion from Integer to Int.
implicit def toInt(in:Integer) = in.intValue()
You'll still get deprecation warning though.

I think the problem you're seeing has has to do boxing/unboxing of value types and the use of the Java class Integer.
I think the answer is here: Boxing and unboxing in Scala. There is no implict unboxing in Scala. You've defined i as the Java class Integer but in the i > 3, the 3 is being treated and an int.

Integer is a Java class, java.lang.Integer. It's different from Java's primitive type int, which is not a class. It can't have < defined, because Java does not allow operators to be defined for classes.
Now, you might wonder why such a type exist at all? Well, primitive types cannot be passed as references, so you can't pass an int to a method expecting java.lang.Object, equivalent to Scala's AnyRef, for example. To do that, you put that int inside an Integer object, and then pass the Integer.

Integer gets imported from java.lang.Integer and is only for compatibility with Java. Since it is a Java class, of course it can't have a method called "<".
EDIT: You can mitigate this problem by declaring an implicit conversion from Integer to Int.

Related

scala: assign null to primitive

I am trying to assign null to a variable which is Double like this:
var foo = 0.0
foo = null
However, this gives an error that null cannot be implicitly converted to Double
So I do this instead:
foo = null.asInstanceOf[Double]
however the new value for foo is 0.0
How can I set the value to null?
You can't. Double is a value type, and you can only assign null to reference types. Instead, the Scala compiler replaces null with a default value of 0.0.
See default values in the SLS 4.2:
default type
0 Int or one of its subrange types
0L Long
0.0f Float
0.0d Double
false Boolean
You cannot assign Java primitives to null, either. And while Scala's Double isn't truly a primitive (it is actually a class in Scala), it needs to compile down to double in Java byte code. Instead, you should use Option[Double] if you want to represent a value that is missing entirely, and try to never use null in Scala.
An alternative (perhaps easiest) approach is just to use java.lang.Double instead of scala.Double, and assign to java.lang.Double.NaN instead of null.
Then you can just do
if(foo.isNaN) { work around not a number case } else { usual case }
when using the variable.
I say this is perhaps easiest because if your intention is to be able to check for Not-Available (or non-existing) status of a Double value, while otherwise using the variable(s) with usual Double arithmetic & operators, then using the java float primitives is quite a bit simpler than aliasing and otherwise working around the wrapper class of Option[Double].
See: Option[Double] arithmetic operators
and Can float (or double) be set to NaN?
To answer your question why the complier complain when assigning a null to double variable, you can easily understand via the scala classes hierarchy diagram:
http://docs.scala-lang.org/tutorials/tour/unified-types.html
In short,
Double is a sub class of Anyval
null (a instance of Null) is a sub class of AnyRef.
So they are different types or classes in scala, it is similar to assign a List to a String.
You should never use null in Scala, instead take a look at Option, Option[Double] specifically
val foo = Some(0.0)
foo = Option.empty[Double]
Even Java introduced it's Optional values, instead of null.
https://docs.oracle.com/javase/8/docs/api/java/util/Optional.html
http://www.scala-lang.org/api/2.7.4/scala/Option.html

Why is String not a value?

scala> val a = Int
a: Int.type = object scala.Int
scala> val a = String
<console>:11: error: object java.lang.String is not a value
val a = String
^
Why didn't scala create a thin wrapper around java.lang.String in order to make String a value? Isn't it very restrictive when one of the main types (String) cannot be used in expressions or passed to / returned from functions?
Well... In Scala class's can have companion objects.
And that companion object for any class A is actually an instance of A.type.
So... when you do,
val i = Int
What you get is companion object of class Int which is an instance of Int.type
Keep in mind that Int is still not a value... this thing that you have is not Int. It is also not an instance of Int. It is an instance of Int.type.
But as far as String is concerned... it is defined as an Alias for the corresponding java.lang.String from the Java world and thus has no such companion object. And hence the val assignment does not work with it.
As for why String is not wrapped in Scala. There can be many reasons for this. But one main reason is because there was no need for that.
Scala wanted to be have pure object hierarchy such that everything is an object and inherits from the same root Any. And Java has basic-types like int, long etc... which are not objects... and this created a need to wrap them into Int.
Although the question probably turns on a misapprehension about reifying a type, the following suggests why you can select Java statics as though they were members of a companion object, even though there is no such object:
$ scala
Welcome to Scala 2.12.1 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_111).
Type in expressions for evaluation. Or try :help.
scala> java.lang.System.currentTimeMillis
res0: Long = 1483263161912
scala> java.lang.System
<console>:12: error: object java.lang.System is not a value
java.lang.System
^
scala> java.lang.System.toString
<console>:12: error: value toString is not a member of object System
Note that System extends Any, not AnyRef.
Such types can participate in value classes, but instances
cannot appear in singleton types or in reference comparisons.
java.lang.System.toString
^
scala>

Why is Scala coercing type from Char to Double?

The following code
object testType extends App {
def func(x:Int) = if(x==0) 1.0 else 'c'
println(func(0))
println(func(1))
}
results in
1.0
99.0
At first when I wrote this, I thought Scala was not going to allow such a function but it interpreted the function as (Int) => Double. This feels like type coercion.
If I substitute the 'c' for "c" in the function above, it actually returns
1.0
c
where the function is now interpreted as (Int) => Any
Questions: if Scala is strongly typed, why did the first example with 'c' returned a Double and why the difference between (Int) => Double and (Int) => Any for the two examples?
There is a relationship between types in Scala called "weak conformance". Char weakly conforms to Double (because it weakly conforms to Int which weakly conforms to Double). The type of if (<cond>) then <e1> else <e2> is defined to be the weak least upper bound (wlub) of types of <e1> and <e2> (there is a similar rule for other expressions with many branches: match and try/catch). The wlub of Char and Double is Double; the wlub of String and Double is Any.
Scala does implicit conversions between types where necessary. Usually it does this through some implicit conversion defined anywhere in scope (most of the implicit conversions are in scala.Predef which is imported by default)
In order to see all available implicit conversions do this in the repl:
:implicits -v
However, if you do that, you will see that there is no implicit conversion available from char2Double. So whats going on? Here, scala compiler resorts to another type of conversion called numeric widening:
If ee has a primitive number type which weakly conforms to the expected type, it is widened to the expected type using one of the numeric conversion methods toShort, toChar, toInt, toLong, toFloat, toDouble defined here.
So, as #Alexey pointed out in his answer that chars weakly conform to Doubles, the char 'c' gets converted to a Double by applying 'c'.toDouble numeric widening conversion.
Also, you can disable implicit conversions that are defined in Predef like this:
// disable int to Integer conversion
import scala.Predef.{int2Integer => _}
However, am not sure whether the numeric widening conversions can be disabled.
As pointed by #pedrorijo91, numeric widening can also be prevented by adding the suitable scalac flags: -Ywarn-numeric-widen & -Xfatal-warnings

Scala - mapping a list of integers to a method that receives java.lang.Object

Working in Scala-IDE, I have a Java library, in which one of the methods receives java.lang.Object. And I want to map a list of Int values to it. The only solution that works is:
val listOfInts = groupOfObjects.map(_.getNeededInt)
for(int <- listOfInts) libraryObject.libraryMethod(int)
while the following one:
groupOfObjects.map(_.getNeededInt).map(libraryMethod(_)
and even
val listOfInts = groupOfObjects.map(_.getNeededInt)
val result = listOfInts.map(libraryObject.libraryMethod(_))
say
type mismatch; found : Int required: java.lang.Object Note: an
implicit exists from scala.Int => java.lang.Integer, but methods
inherited from Object are rendered ambiguous. This is to avoid a
blanket implicit which would convert any scala.Int to any AnyRef. You
may wish to use a type ascription: x: java.lang.Integer.
and something like
val result = listOfInts.map(libraryObject.libraryMethod(x => x.toInt))
or
val result = listOfInts.map(libraryObject.libraryMethod(_.toInt))
does not work also.
1) Why is it happening? As far as I know, the for and map routines do not differ that much!
2) Also: what means You may wish to use a type ascription: x: java.lang.Integer? How would I do that? I tried designating the type explicitly, like x: Int => x.toInt, but that is too erroneus. So what is the "type ascription"?
UPDATE:
The solution proposed by T.Grottker, adds to it. The error that I am getting with it is this:
missing parameter type for expanded function ((x$3) => x$3.asInstanceOf[java.lang.Object])
missing parameter type for expanded function ((x$3) => x$3.asInstanceOf{#null#}[java.lang.Object]{#null#}) {#null#}
and I'm like, OMG, it just grows! Who can explain what all these <null> things mean here? I just want to know the truth. (NOTE: I had to replace <> brakets with # because the SO engine cut out the whole thing then, so use your imagination to replace them back).
The type mismatch tells you exactly the problem: you can convert to java.lang.Integer but not to java.lang.Object. So tell it you want to ask for an Integer somewhere along the way. For example:
groupOfObjects.map(_.getNeededInt: java.lang.Integer).map(libraryObject.libraryMethod(_))
(The notation value: Type--when used outside of the declaration of a val or var or parameter method--means to view value as that type, if possible; value either needs to be a subclass of Type, or there needs to be an implicit conversion that can convert value into something of the appropriate type.)

Implicit conversions for value class types?

I read about implicit conversions being done between different value class types. The book "Programming in Scala" states:
[...] an instance of class scala.Int is automatically widened (by an implicit conversion) to an instance of class scala.Long when required.
(Ch. 11.1 - Scala's Hierarchy)
What does "required" mean in this case? How can one make this "visible"? I assumed:
scala> var i = Int.MaxValue
i: Int = 2147483647
I was expecting i: Long = 2147483648 if I add 1.
scala> i = i + 1
i: Int = -2147483648
I was not expecting to see an overflow.
"Required" means a method that takes a Long being passed an Int and stuff like that.
Int.+ does not require a Long. For the most part, Ints behave just like Java's primitive integer type.