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
Related
I know one is not supposed to use nulls in scala but sometimes when interoperating with Java it happens. The way a scala mutable map handles this seems off though:
scala> import scala.collection.mutable
import scala.collection.mutable
scala> val m: mutable.Map[String, String] = mutable.Map.empty
m: scala.collection.mutable.Map[String,String] = Map()
scala> m.put("Bogus", null)
res0: Option[String] = None
scala> m.get("Bogus")
res1: Option[String] = Some(null)
scala> m.getOrElse("Bogus", "default")
res2: String = null
I would have expected m.get to return None in this case. Almost seems like a bug, like somewhere in the code there was a Some(v) instead of Option(v)
Is there discussion w/r/t to changing this behavior?
I would have expected m.get to return None in this case.
Why? None would mean the key "Bogus" is not in the map, but you just put it in (with value null).
Java's Map API has problems distinguishing "the value for this key is null" from "this key is not in the map", but Scala's doesn't.
Null is subtype of String:
scala> implicitly[Null <:< String]
res3: Null <:< String = <function1>
Therefore null is a valid String value:
scala> val s: String = null
s: String = null
If you want to store a null as a String in a map, it's your good right.
Compared to Java's Map#get (let's call it javaLikeGet), the Scala's get behaves roughly as follows:
def get(k: K) = if (containsKey(k)) {
Some(this.javaLikeGet(k))
} else {
None
}
and not like what you have assumed:
def get(k: K) = Option(this.javaLikeGet(k))
The latter version (presumably what you thought) would get a null for an existing key, pass it to Option(...), and return None. But the former version (which imitates how the real implementation works) would notice that the key exists, and wrap the null returned by javaLikeGet into a Some.
The simple and consistent rule is:
If the key k exists, then get(k) returns Some[V], otherwise it returns None.
This is much less surprising than the strange behavior of Java's get that returns null in two entirely different situations.
This is the Billion-Dollar Mistake, but Scala is not the language that is likely to fix it, because it has to interop with Java. My guess is that there is and will be no discussion about changing this behavior, at least not until something fundamentally changes in the entire programming landscape.
I am trying to understand why exactly an implicit conversion is working in one case, but not in the other.
Here is an example:
case class Wrapper[T](wrapped: T)
trait Wrapping { implicit def wrapIt[T](x: Option[T]) = x.map(Wrapper(_))
class NotWorking extends Wrapping { def foo: Option[Wrapper[String]] = Some("foo") }
class Working extends Wrapping {
def foo: Option[Wrapper[String]] = {
val why = Some("foo")
why
}
}
Basically, I have an implicit conversion from Option[T] to Option[Wrapper[T]], and am trying to define a function, that returns an optional string, that gets implicitly wrapped.
The question is why, when I try to return Option[String] directly (NotWorking above), I get an error (found : String("foo") required: Wrapper[String]), that goes away if I assign the result to a val before returning it.
What gives?
I don't know if this is intended or would be considered a bug, but here is what I think is happening.
In def foo: Option[Wrapper[String]] = Some("foo") the compiler will set the expected type of the argument provided to Some( ) as Wrapper[String]. Then it sees that you provided a String which it is not what is expected, so it looks for an implicit conversion String => Wrapper[String], can't find one, and fails.
Why does it need that expected type stuff, and doesn't just type Some("foo") as Some[String] and afterwards try to find a conversion?
Because scalac wants to be able to typecheck the following code:
case class Invariant[T](t: T)
val a: Invariant[Any] = Invariant("s")
In order for this code to work, the compiler can't just type Invariant("s") as Invariant[String] because then compilation will fail as Invariant[String] is not a subtype of Invariant[Any]. The compiler needs to set the expected type of "s" to Any so that it can see that "s" is an instance of Any before it's too late.
In order for both this code and your code to work out correctly, I think the compiler would need some kind of backtracking logic which it doesn't seem to have, perhaps for good reasons.
The reason that your Working code does work, is that this kind of type inference does not span multiple lines. Analogously val a: Invariant[Any] = {val why = Invariant("s"); why} does not compile.
Given:
val personsOpt:Option[List[Person]] = ???
I prefer:
persons = personsOpt.fold(List[Person]()){person => person}
To this:
persons = personsOpt.getOrElse(List[Person]())
For type safety reasons. For example this does not compile:
persons = personsOpt.fold(Nil){person => person}
Is there a simple way to get the type safety but not have {person => person}?
EDIT: Two things now concretely understood:
There is nothing un-type-safe about getOrElse. For instance this does not compile: personsOpt.getOrElse("")
Nil is List() and if its type can't be inferred the compiler will ask you to be explicit. So there can be no type issues with using Nil
I couldn't find the link just now, but I did (incorrectly) read that getOrElse was somehow less type safe than using fold with an Option.
There is the function identity which is defined in Predef:
persons = personsOpt.fold(List[Person]())(identity)
I find this however a lot less readable than using getOrElse, and using this does not make your code more type-safe than using getOrElse. Note that passing Nil to getOrElse will make it return the correct type:
scala> case class Person(name: String)
scala> val personsOpt:Option[List[Person]] = None
personsOpt: Option[List[Person]] = None
scala> val persons = personsOpt.getOrElse(Nil)
persons: List[Person] = List()
Note that persons is a List[Person].
I have read that null should not be used in scala.
How can I leave myVar uninitialized without the use of null?
class TestClass {
private var myVar: MyClass = null
}
I understand I can just make a dummy MyClass, that is never used in place of the null. But this can and does reduce the code's understandability.
As Rado has explained I can change null as shown below. I understand that I can now check to see if the variable is set during run-time, however, if I don't program that check then there is no benefit of using Option in this case.
Coming from Java, I feel there should be a way to simply leave the var uninitialized at compile-time and let it set during run-time without using the Option class, because as I mentioned above, if I don't code for the unset case then why use Option?
class TestClass {
private var myVar: Option[MyClass] = None
private def createVar() {
myVar = Some(new MyClass)
x: MyClass = myVar.get
}
}
I am thinking the only other way of doing what I am asking is:
class TestClass {
// Using dummy MyClass that will never be used.
private var myVar: MyClass = new MyClass
private def process(myVar: MyClass) {
this.myVar = myVar
myVar.useVarMethod()
}
}
The Scala way is to declare the variable as Option[MyClass]:
class TestClass {
private var myVar: Option[MyClass] = None
private def createVar() {
myVar = Some(new MyClass)
}
// Usage example:
def useMyVar(): Unit = {
myVar match {
case Some(myClass) => {
// Use myClass here ...
println(myClass.toString)
}
case None => // What to do if myVar is undefined?
}
}
}
That way you avoid NullPointerException. You make it explicit that the variable can be in undefined state. Everytime you use the myVar you have to define what to do if it is undefined.
http://www.scala-lang.org/api/current/index.html#scala.Option
I need myVar to be of type MyClass not Option[MyClass]. I see that I
could use Rado's updated answer and then use the get method, but is
there any other way?
When you use Option you can telling the compiler and everyone else who will read/use your code that it's okay not to define this value and the code will handle that condition and not fail at runtime.
The other way of dealing with is to do null checks every time before you access the variable because it could be null and therefore throw an exception at runtime.
When you use Option, the compiler will tell you if at compile time that you have not handled a condition where the value of a variable maybe undefined.
If you think about it, it's really a big deal. you have converted a runtime exception (which is deterministic) to a compile-time error.
If you want to extract the value out of something like an Option (which supports map and also flatMap), then you don't necessarily have to keep doing pattern matching on whether or not the Option contains a value (i.e. is a "Some") or not (i.e. is a "None").
Two methods are very useful - if you want just alter (or "map") the value within the Option then you can use the map method, which takes a function with a general type of:
f: A => B
so in your case at compile time would end up being:
f: MyClass => B
When you map an option, if the option is a "Some" then the contained value is passed through to the mapping function, and the function is applied (to change the MyClass to a B if you like...) and the result is passed back wrapped in an Option. If your Option is a None, then you just get a None back.
Here's a simple example:
scala> case class MyClass(value : String)
defined class MyClass
scala> val emptyOption : Option[MyClass] = None
emptyOption: Option[MyClass] = None
scala> val nonEmptyOption = Some(new MyClass("Some value"))
nonEmptyOption: Option[MyClass] = Some(MyClass(Some value)
Try and extract the value from both option instances using map:
scala> nonEmptyOption map { s => s.value + " mapped" }
res10: Option[String] = Some(Some value mapped)
scala> emptyOption map { s => s.value }
res11: Option[String] = None
So basically, if you map across an empty option, you always get a None. Map across a non-empty Option and you can extract the contained value and transform it and get the result wrapped back in an Option. Notice that you don't need to explicitly check any patterns...the map method takes care of it.
Flatmap is a bit more challenging to explain, but it basically isn't massively different except that it takes a function which has type:
g: A => M[B]
which basically allows you to take the value out of the Option (the 'A' in the type signature above), do something to it (i.e. a computation) and then return the result ('B') - wrapped in another container such as another Option, List...
The same notion (across Option anyway) that if the Option is a None then nothing really happens still applies. flatMap and map form the basis of Scala "for comprehensions" which you can read about (and are done far more justice than I could!!) in lots of other places.
I have been playing lately with compound types and I recently was trying the following code:
import scala.reflect._
object Main {
def main(args: Array[String]) {
val a1 = classTag[Int with String with Double].newArray(3)
println(a1.mkString(" "))
val a2 = classTag[String with Int with Double].newArray(3)
println(a2.mkString(" "))
val a3 = classTag[Double with Int with String].newArray(3)
println(a3.mkString(" "))
}
}
With the following output:
0 0 0
null null null
0.0 0.0 0.0
It results a bit strange to me. Each of the array elements has access to the methods of the three types: Int, String and Double. What is happening exactly behind scene here? The compound types are actually instances of the first type? Can a compound type being instanced explicitly? Their use case is only for when the types composing the compound are related through inheritance and so on? Thanks.
P.S.: I'm using Scala 2.11.4
What is happening exactly behind scene here? The compound types are actually instances of the first type?
Looking at the newArray method as defined for ClassTag:
override def newArray(len: Int): Array[T] =
runtimeClass match {
case java.lang.Byte.TYPE => new Array[Byte](len).asInstanceOf[Array[T]]
case java.lang.Integer.TYPE => new Array[Int](len).asInstanceOf[Array[T]]
/* snip */
case _ => java.lang.reflect.Array.newInstance(runtimeClass, len).asInstanceOf[Array[T]]
}
And then your type:
scala> classTag[Int with String with Double].runtimeClass
res4: Class[_] = int
It seems pretty clear how it's arriving at the conclusion to use the first type. The runtimeClass of Int with String with Double is Int, and the newArray method uses the runtimeClass to construct the new Array. So the Array is filled with default Int values. Likewise for the other order combinations.
Why is the runtime class Int? Well, Int with String with Double isn't an actual class, but Int is. The compiler's choice of which class to use can't just be arbitrary, so why not the first?
Can a compound type be instanced explicitly?
I'm not sure what you mean by this. If you think about it, the compiler kind of has to favor one type in this composition. What would an explicit Int with String with Double look like? What about Int with String with Double with Product with Process ? I don't know, either.
Each of the array elements has access to the methods of the three types: Int, String and Double
They do, and yet they don't.
scala> val arr = classTag[Int with Process].newArray(3)
arr: Array[Int with Process] = Array(0, 0, 0)
scala> arr(0).exitValue()
java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.Process
You're really just tricking the compiler into believing you have an Array of these types, when in fact you don't (and can't, because nothing can be a sub-type of both Int and Process).
Their use case is only for when the types composing the compound are related through inheritance and so on?
Pretty much, yes. I can't think if any situation in which you'd ever want to try to build these types directly. Their main use case is to guarantee that a type inherits from other specific types.
For example, a method that requires that a parameter inherit methods from two traits:
trait Hello { def hello = println("Hello") }
trait Bye { def bye = println("Bye") }
def greet(hb: Hello with Bye): Unit = { hb.hello; hb.bye }
class A extends Hello
class B extends Hello with Bye
scala> greet(new A)
<console>:15: error: type mismatch;
found : A
required: Hello with Bye
greet(new A)
^
scala> greet(new B)
Hello
Bye