Pass null to a method expects Long - scala

I have a Scala method that takes 2 parameters:
def test(x:Long,y:Int){}
On some occasion I need to pass null instead of long ... something like that:
test(null,x)
The result:
scala> test(null,2) :7: error: type mismatch; found :
Null(null) required: Long
test(null,2)
Why do I need to pass null?
Actually ,for some reason,I can't pass any default values.
Thus, I need such a null.
*Note:*I know that the solution would be making it Option.
However let's say I have no control over this method signature,can I do any work around?
Any ideas!
Thanks.

Null is a subtype of types which inherit from AnyRef, not from value types which inherit from AnyVal. This is why you are not able to pass null in. This corresponds to how, in java, you cant have a null of type long. (ignoring the boxed Long type).
However, this is an indication that the signature of the method should be changed to:
def test(x: Option[Long], y: Int)
which indicates that sometimes it goes no value for x. Since we have this nice Option class to deal with just this instance, there is little if any valid reasons to use null values, where you are relying on developers remembering to check for null values. Instead, with Option, the compiler will force you to take care of the fact that the value might not be there.

Since you can't change the signature, consider the mistake of Thinking Option[Foo] is the only/most natural way to express a missing function argument.
If the param to your function is a lower bound, then Long.MinValue might be a natural default.
If by "for some reason,I can't pass any default values" (whatever that could possibly mean) you mean you can't add defaults to the signature, and you're going the route suggested in another answer of adapting the method, you might as well change f(a,b) to g(b, a=Long.MinValue) or whatever before forwarding.
Instead of making clients of your adaptor method call g(b, None), let them call g(b). You're not passing the Option to the underlying f(a,b) anyway.

The way to convert scala primitives to Java wrapper classes, is to use the static valueOf members on the Java Primitive wrappers. I had this issue where I needed to convert an Option[Double] to a java.lang.Double or null. This is what I did:
val value: Option[Double]
val orNull = value.map(java.lang.Double.valueOf(_)).orNull
Just passing literal null should work if you are calling a method that accepts java.lang.Long/Double/Integer

Related

Disfunctionality of type parameter

I’m new to using Scala and am trying to see if a list contains any objects of a certain type.
When I make a method to do this, I get the following results:
var l = List("Some string", 3)
def containsType[T] = l.exists(_.isInstanceOf[T])
containsType[Boolean] // val res0: Boolean = true
l.exists(_.isInstanceOf[Boolean]) // val res1: Boolean = false
Could someone please help me understand why my method doesn’t return the same results as the expression on the last line?
Thank you,
Johan
Alin's answer details perfectly why the generic isn't available at runtime. You can get a bit closer to what you want with the magic of ClassTag, but you still have to be conscious of some issues with Java generics.
import scala.reflect.ClassTag
var l = List("Some string", 3)
def containsType[T](implicit cls: ClassTag[T]): Boolean = {
l.exists(cls.runtimeClass.isInstance(_))
}
Now, whenever you call containsType, a hidden extra argument of type ClassTag[T] gets passed it. So when you write, for instance, println(containsType[String]), then this gets compiled to
scala.this.Predef.println($anon.this.containsType[String](ClassTag.apply[String](classOf[java.lang.String])))
An extra argument gets passed to containsType, namely ClassTag.apply[String](classOf[java.lang.String]). That's a really long winded way of explicitly passing a Class<String>, which is what you'd have to do in Java manually. And java.lang.Class has an isInstance function.
Now, this will mostly work, but there are still major caveats. Generics arguments are completely erased at runtime, so this won't help you distinguish between an Option[Int] and an Option[String] in your list, for instance. As far as the JVM is concerned, they're both Option.
Second, Java has an unfortunate history with primitive types, so containsType[Int] will actually be false in your case, despite the fact that the 3 in your list is actually an Int. This is because, in Java, generics can only be class types, not primitives, so a generic List can never contain int (note the lowercase 'i', this is considered a fundamentally different thing in Java than a class).
Scala paints over a lot of these low-level details, but the cracks show through in situations like this. Scala sees that you're constructing a list of Strings and Ints, so it wants to construct a list of the common supertype of the two, which is Any (strings and ints have no common supertype more specific than Any). At runtime, Scala Int can translate to either int (the primitive) or Integer (the object). Scala will favor the former for efficiency, but when storing in generic containers, it can't use a primitive type. So while Scala thinks that your list l contains a String and an Int, Java thinks that it contains a String and a java.lang.Integer. And to make things even crazier, both int and java.lang.Integer have distinct Class instances.
So summon[ClassTag[Int]] in Scala is java.lang.Integer.TYPE, which is a Class<Integer> instance representing the primitive type int (yes, the non-class type int has a Class instance representing it). While summon[ClassTag[java.lang.Integer]] is java.lang.Integer::class, a distinct Class<Integer> representing the non-primitive type Integer. And at runtime, your list contains the latter.
In summary, generics in Java are a hot mess. Scala does its best to work with what it has, but when you start playing with reflection (which ClassTag does), you have to start thinking about these problems.
println(containsType[Boolean]) // false
println(containsType[Double]) // false
println(containsType[Int]) // false (list can't contain primitive type)
println(containsType[Integer]) // true (3 is converted to an Integer)
println(containsType[String]) // true (class type so it works the way you expect)
println(containsType[Unit]) // false
println(containsType[Long]) // false
Scala uses the type erasure model of generics. This means that no
information about type arguments is kept at runtime, so there's no way
to determine at runtime the specific type arguments of the given
List object. All the system can do is determine that a value is a
List of some arbitrary type parameters.
You can verify this behavior by trying any List concrete type:
val l = List("Some string", 3)
println(l.isInstanceOf[List[Int]]) // true
println(l.isInstanceOf[List[String]]) // true
println(l.isInstanceOf[List[Boolean]]) // also true
println(l.isInstanceOf[List[Unit]]) // also true
Now regarding your example:
def containsType[T] = l.exists(_.isInstanceOf[T])
println(containsType[Int]) // true
println(containsType[Boolean]) // also true
println(containsType[Unit]) // also true
println(containsType[Double]) // also true
isInstanceOf is a synthetic function (a function generated by the Scala compiler at compile-time, usually to work around the underlying JVM limitations) and does not work the way you would expect with generic type arguments like T, because after compilation, this would normally be equivalent in Java to instanceof T which, by the way - is illegal in Java.
Why is illegal? Because of type erasure. Type erasure means all your generic code (generic classes, generic methods, etc.) is converted to non-generic code. This usually means 3 things:
all type parameters in generic types are replaced with their bounds or Object if they are unbounded;
wherever necessary the compiler inserts type casts to preserve type-safety;
bridge methods are generated if needed to preserve polymorphism of all generic methods.
However, in the case of instanceof T, the JVM cannot differentiate between types of T at execution time, so this makes no sense. The type used with instanceof has to be reifiable, meaning that all information about the type needs to be available at runtime. This property does not apply to generic types.
So if Java forbids this because it can't work, why does Scala even allows it? The Scala compiler is indeed more permissive here, but for one good reason; because it treats it differently. Like the Java compiler, the Scala compiler also erases all generic code at compile-time, but since isInstanceOf is a synthetic function in Scala, calls to it using generic type arguments such as isInstanceOf[T] are replaced during compilation with instanceof Object.
Here's a sample of your code decompiled:
public <T> boolean containsType() {
return this.l().exists(x$1 -> BoxesRunTime.boxToBoolean(x$1 instanceof Object));
}
Main$.l = (List<Object>)package$.MODULE$.List().apply((Seq)ScalaRunTime$.MODULE$.wrapIntArray(new int[] { 1, 2, 3 }));
Predef$.MODULE$.println((Object)BoxesRunTime.boxToBoolean(this.containsType()));
Predef$.MODULE$.println((Object)BoxesRunTime.boxToBoolean(this.containsType()));
This is why no matter what type you give to the polymorphic function containsType, it will always result in true. Basically, containsType[T] is equivalent to containsType[_] from Scala's perspective - which actually makes sense because a generic type T, without any upper bounds, is just a placeholder for type Any in Scala. Because Scala cannot have raw types, you cannot for example, create a List without providing a type parameter, so every List must be a List of "something", and that "something" is at least an Any, if not given a more specific type.
Therefore, isInstanceOf can only be called with specific (concrete) type arguments like Boolean, Double, String, etc. That is why, this works as expected:
println(l.exists(_.isInstanceOf[Boolean])) // false
We said that Scala is more permissive, but that does not mean you get away without a warning.
To alert you of the possibly non-intuitive runtime behavior, the Scala compiler does usually emit unchecked warnings. For example, if you had run your code in the Scala interpreter (or compile it using scalac), you would have received this:

scala method with 2 generics where one can be inferred

I'm new to Scala. I am writing a method which sends a request of type RQ to a server, and receives a response of type Response[RSP]. The simplified version: I define a method to make a call:
def invoke[RQ, RSP](request: RQ): Response[RSP] = {....}
When I invoke the method, all parameters can be inferred if I specify the type of the receiving variable, like this:
val result: Response[Double] = invoke("Hello")
But if I just say invoke("Hello") without assigning it to anything, it won't compile. I have to supply the 2 generic types (e.g invoke[String, Double]("Hello") ). My question is: The String can be inferred from the parameter. Is there a way to write the call specifying only the RSP generic? Something in the lines of : invoke[ , Double]("Hello") ?
No.
This is a feature that has been asked about a number of times. Future versions of Scala may support a syntax similar to named arguments for methods:
invoke[RSP = Double]("Hello")
At the moment, there is nothing much you can do except restructure your code so that the method has only one type parameter, and the second comes from the surrounding context.
The more interesting question is: why do you even care about the return type if you just throw away the result anyway? It looks like your method violates the Command-Query Separation Principle. If your method simply returned Unit, you wouldn't need the second type parameter, and all would work fine. If you actually used the return value, the type inferencer would at least have a chance to infer the second type parameter from the context. But the fact that you have a type parameter for the return value but ignore the return value means that there is no context for the type inferencer to look at.

Constraint a scala type such that I would never need to check for null?

def myMethod(dog: Dog) = {
require (dog != null) // is it possible to already constraint it in the `Dog` type?
}
Is there a way to construct Dog such that it would be an ADT which would never be able to accept a null thus eliminate any null check? (I don't want an Option here, otherwise all my code would turn to have Option based, I want to already constraint the Dog class such that null is never possible, this is why type system is for to allow me to specify constraints in my program).
There was an attempt to provide such functionality (example I'm running in 2.10.4):
class A extends NotNull
defined class A
val x: A = null
// <console>:8: error: type mismatch;
// found : Null(null)
// required: A
// val x: A = null
^
Though it was never complete and eventually got deprecated. As for the time of writing, I don't think it's possible to construct ones hierarchy in a way that prevent you from nulls, without additional nullity checking analysis.
Check out comments in relevant ticket for an insight
I don't think this is possible, generally, because Java ruins everything. If you have a Java method that returns Dog, that could give you a null no matter what language/type features you add to Scala. That null could then be passed around, even in Scala code, and end up being passed to myMethod.
So you can't have non-null types in Scala without losing the interoperability property that Scala objects are Java objects (at least for the type in question).
Unfortunately inheritance makes it very difficult for the computer to know in the general case whether a method could be passed an object that originated from Java - unless everything is final/sealed, you can always subclass a class that handled the object at some point, and override the Dog-returning method. So it requires hairy full-program analysis to figure out the concrete types of everything (and remember, which concrete types are used can depend on runtime input!) just to establish that a given case could not involve Java code.

Why is a to `Any` casted `String` object no more considered as String (while the other way round it is)?

When casting a String to the type Any, it will no more be considered automatically as String -- why ? See the following example:
val str = "foo"
val strAsAny = "bar".asInstanceOf[Any]
def f1(x: String) = println(x.toString)
def f2(x: Any) = println(x.toString)
f1(str) // works, type exactly given
f2(str) // works, subtype of Any given
f1(strAsAny) // works not, but strAsAny.isInstanceOf[String] = true !
f2(strAsAny) // works, type exactly given
This confuses me a bit, because both values do still have the type String :
scala> str.isInstanceOf[String]
res4: Boolean = true
scala> strAsAny.isInstanceOf[String]
res5: Boolean = true
My guess is, that only type conversions "to get upwards" of the interhitance-chain will be done automatically. Is this correct ?
Types specify what you expect, not what you've actually got. You can place anything that satisfies what you expect into that slot.
With Any, you expect very little, so anything works. With String, you expect length, charAt, etc.. So a String can satisfy the requirements of an Any but not vice versa. If you happen to put a String into an Any slot, you are now only promising to do what Any can, so you can't take that value and give it to something expecting a String.
This is called the Liskov Substitution Principle and is a fundamental principle of (safe) object-oriented design.
You are conflating static types with dynamic types.
A static type is what the compiler knows, and is something that exists at compile time.
That is, when you do this:
val strAsAny = "bar".asInstanceOf[Any]
Then the compiler will know (or think) that strAsAny has type Any. It won't know there's a String stored in there.
Mind you, avoid as much as possible asInstanceOf, since most valid uses of it can be replaced by type ascription ("bar" : Any) or pattern matching (case anyAsStr: String => "got a String"), both of which are safe. The operator asInstanceOf is not safe, because it tells the compiler to ignore what it knows, and believe what you are telling it, even when it knows it's wrong.
So, asInstanceOf is mostly a compile-time operator, though it also produces some code for the JVM to execute.
Now, what the compiler thinks matter because it only let you call methods it knows can be called. So even though, at run time, strAsAny will contain a String, the compiler doesn't know that. You told it to forget that "bar" is a String, and it did so. Therefore, you are not allowed to call String methods on it.
On the other hand, a dynamic type is what is true at run time. In most cases, for a language like Scala, the compiler has no way of knowing what will be true or not at run time.
And whether the compiler can know something or not, isInstanceOf is a run time operation. The compiler doesn't have anything to say about what will happen.
So, when you do this:
strAsAny.isInstanceOf[String]
The compiler doesn't care -- it just compiles the code. When you execute the code, then the JVM will verify what kind of value is stored inside strAsAny, and verify that it is, indeed, a String, and then return true.

Cast values from Any using ClassManifest in Scala

I've got a List[Any] of values and a list of corresponding ClassManifest[_]s, storing values' original types. How do i cast some value from list back to it's original type?
def cast[T](x: Any, mf: ClassManifest[T]): T = x.asInstanceOf[T] doesn't work.
Thank You for your answers.
That can't ever possibly work, as the return type of cast will always be taken as the highest common supertype of whatever T is restricted to. There's no way it can be made any more specific at compile time.
If you're trying to build a strongly-typed collection of disparate types, then what you really want is an HList:
http://jnordenberg.blogspot.com/2008/09/hlist-in-scala-revisited-or-scala.html
The way to use a Class instance in Java/Scala to cast an object is to use the Class.cast method. So you may think that you could do:
mf.erasure.cast(x) //T
But this will not work, because mf.erasure is a Class[_] (or a Class<?> in Java), so the cast is meaningless (i.e. offers no extra information). This is (of course) one of the drawbacks in using non-reified generics.