In Scala,Why is it not possible to change the value of var variable with different datatype - scala

I am learning scala, trying to understand var variable .
Look at my below code
scala> var id =10
id: Int = 10
scala> id ="surender"
<console>:12: error: type mismatch;
found : String("surender")
required: Int
id ="surender"
var is mutable, that means we can change the value, While changing the value do we need to stick with same datatype?
Does it mean statically typed language?

Yes Scala is indeed a statically typed language. You can't reassign the data type at runtime.
The concept is called type safety and a lot people value it deeply. It is a matter of preference however.

You can specify the type when creating a var (or a val):
var id: Any = 10 // Don't actually do this!
id = "surender" // works
If you don't, the compiler infers the type from the initializer (in this case type of 10 is Int). However, Scala is indeed statically typed and there is very little you can usefully do with something of type Any. This is more useful e.g. in this situation:
var x: Option[Int] = None
x = Some(10) // doesn't compile without the signature above

Related

when does it need explicit type when declare variable in scala?

Here is a simple sample code for my question.
var a:Int=1; //line 1
var a=1; //line 2
Is Int in line 1 needed? or must?
if not ,can I delete it like in line 2?
Since 1 is of type Int, compiler knows that a is of type Int too.
This is called type inference.
You should specify a type explicitly when this is better for code readability.
You must specify a type when compiler can't infer the type or when this helps to infer other types.
In Scala type inference can go in both directions, from right to left and vice versa. For example in val a = 1 type of a is inferred from type of 1, so type inference went from right to left. In
def myMethod[T](): T = ???
val n: Int = myMethod()
since n is expected to be an Int, compiler infers that T in myMethod() should be Int too, so type inference went from left to right.
https://twitter.github.io/scala_school/type-basics.html#inference
http://www.scala-lang.org/old/node/127
http://allaboutscala.com/tutorials/chapter-2-learning-basics-scala-programming/scala-tutorial-overview-scala-type-inference/
How does scala infers the type of a variable?
You don't need to specify the type Int in this case, as it is inferred by the compiler.
There is plenty of documentation about type inference in scala. Check this out: http://docs.scala-lang.org/tour/local-type-inference.html
In most cases the Scala compiler can deduce types automatically. In these cases you do not have to explicitly define the type of your variable declaration.
var a = 1
is perfectly valid Scala code.
It is often recommended to declare explicitly the return types of public methods.

How do I write a shorthand for a datatype in Scala

How do I write shorthand for a datatype?
For example.
lets say instead of List[Integer], I would rather type Integers
instead of this
def processNumbers(input:List[Integer]):List[Integer] = ...
to
def processNumbers(input:Integers):Integers = ...
Is this possible?
Thanks
Yes, you can do this with a type alias.
type Integers = List[Int] // scala.Int is preferred over java.lang.Integer
That being said, this isn't really a good use for them. List[Int] is very clear to other scala developers, wheres your type Integers provides no extra information and so will detract from the readability of your code over time.
A use of type aliases that would improve your code's readability though would be something like
type UserId = Int
def processUsers(ids: List[UserId]): Foo
In this case it provides extra information to the reader vs
def processUsers(ids: List[Int]): Foo
Using that kind of type alias also will allow you to gradually make your code more type-safe over time by changing the definition from a type alias to a value class.
case class UserId(value: Int) extends AnyVal
You won't need to change the method signatures of anything already having "UserId", but this will let the compiler assist you in making sure you don't do something like
val ids: List[Int] = getBlogPostIds()
val foo = processUsers(ids) // Oops, those Ints are for blog posts, not users
Using the value class approach, a mistake like that becomes a compiler error. Used pervasively it adds quite a lot of guidance in writing correct code.
val ids: List[BlogPostId] = getBlogPostIds
val foo = processUsers(ids) // Compile error; BlogPostId != UserId

Why I'm not able to declare variable of parameterized type initialized with null?

Why doesn't this work?
trait testtrait[T] {
var ob:T = null
}
then scalac testtrait.scala produces
testtrait.scala:2: error: type mismatch;
found : Null(null)
required: T
var ob:T = null
^
one error found
I'm using Scala 2.9
I can't say why exactly, but underscore notion (which is shortcut for default value for type, which is null for objects) will work fine:
trait testtrait[T] {
var ob:T = _
}
More dreaded workaround is asInstanceOf cast, but I found underscore better alternative.
trait testtrait[T] {
var ob:T = null.asInstanceOf[T]
}
null is a value of type Null, but not any type has Null as a subtype, only AnyRef-derived ones (except Nothing, of course). Suppose that you did something like
object SomeObj extends testtrait[Int]
What SomeObj.ob should be equal to? It is an Int, so it does not have null as a possible value.
As it is said in other answers, you should use underscore syntax to set default value for the type.
The bottom type of all types is Nothing. That means any type T, not otherwise constrained, can be Nothing, and null is not a Nothing (in fact, no value is).
So, to be able to assign null, you'd have to write it [T >: Null] (T is a supertype of Null).
On the other hand, you can initialize it to the default value using var ob: T = _. However, be aware that for any AnyVal, T will be boxed and assigned null instead of, say, 0, which can lead to unexpected results.

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

Is this the proper way to initialize null references in Scala?

Let's say I have a MyObject instance which is not initialized:
var a:MyObject = null
is this the proper way to initialize it to null?
Alternatives
Use null as a last resort. As already mentioned, Option replaces most usages of null. If you using null to implement deferred initialisation of a field with some expensive calculation, you should use a lazy val.
Canonical initialisation to null
That said, Scala does support null. I personally use it in combination with Spring Dependency Injection.
Your code is perfectly valid. However, I suggest that you use var t: T = _ to initialize t to it's default value. If T is a primitive, you get the default specific to the type. Otherwise you get null.
Not only is this more concise, but it is necessary when you don't know in advance what T will be:
scala> class A[T] { var t: T = _ }
defined class A
scala> new A[String].t
res0: String = null
scala> new A[Object].t
res1: java.lang.Object = null
scala> new A[Int].t
res2: Int = 0
scala> new A[Byte].t
res3: Byte = 0
scala> new A[Boolean].t
res4: Boolean = false
scala> new A[Any].t
res5: Any = null
Advanced
Using var t: T= null is a compile error if T is unbounded:
scala> class A[T] { var t: T = null }
<console>:5: error: type mismatch;
found : Null(null)
required: T
class A[T] { var t: T = null }
You can add an implicit parameter as evidence that T is nullable -- a subtype of AnyRef not a subtype of NotNull This isn't fully baked, even in Scala 2.8, so just consider it a curiousity for now.
scala> class A[T](implicit ev: Null <:< T) { var t: T = null }
defined class A
The canonical answer is don't use null. Instead, use an option type:
var a = None : Option[MyObject]
When you want to set it:
a = Some(foo)
And when you want to read from it, test for None:
a match {
case None => Console.println("not here")
case Some(value) => Console.println("got: "+value)
}
As David and retronym have already mentioned, it's a good idea to use Option in most cases, as Option makes it more obvious that you have to handle a no-result situation. However, returning Some(x) requires an object creation, and calling .get or .getOrElse can be more expensive than an if-statement. Thus, in high-performance code, using Option is not always the best strategy (especially in collection-lookup code, where you may look up a value very many times and do not want correspondingly many object creations). Then again, if you're doing something like returning the text of an entire web page (which might not exist), there's no reason not to use Option.
Also, just to add to retronym's point on generics with null, you can do this in a fully-baked way if you really mean it should be null:
class A[T >: Null] { var t: T = null }
and this works in 2.7 and 2.8. It's a little less general than the <:< method, because it doesn't obey NotNull AFAIK, but it otherwise does exactly what you'd hope it would do.
I came across this question since scalastyle told me to not use null when initialising an object within my test with null.
My solution without changing any type that satisfied scalastyle:
var a: MyObject = (None: Option[MyObject]).orNull