i'm new to scala and trying some handson exercises .
i'm trying to use implicits by placing implicits in a companion object . however , the compiler doesn't detect implicit unless it is used .
class ImplicitTest {
import Implicits.implicitInt;
println(implicitInt)
def implicitm1(implicit i : Int) = 1
println(implicitm1)
}
object Implicits {
implicit val implicitInt = 1
}
This compiles fine . However if i comment out the third line
\\println(implicitInt)`
then i get a compile-time errors on
println(implicitm1)`
which says
could not find implicit value for parameter i:Int`
not enough arguments for method implicit m1(implicit i:Int) . Unspecified value parameter i`
what did i do wrong here ?
Thanks in advance
If you include the type for val implicitInt: Int = 1, it works. Issues like this are one of the reasons it's recommended to always specify types for implicits.
Scala type inference works from top to bottom, so in your case the compiler doesn't yet know this type when it gets to typechecking the println(implicitm1) line.
I guess that when you include println(implicitInt), the compiler is forced to find implicitInt's type at that line.
Another solution is to move the object Implicits definition above the class ImplicitTest.
In this case the type for implicitInt is already inferred.
Related
I wonder if it is possible to do something like the following:
import scala.reflect.runtime.universe._
class Bar[T]
def foo[T]()(implicit ctag: reflect.ClassTag[T]) {
val clazz = classOf[Bar[ctag.runtimeClass.asInstanceOf[Class[T]]]]
}
Here the Scala compiler complains:
error: stable identifier required, but ctag.runtimeClass found.
Is there a way to get the class type with type parameters inserted from the runtime type information available in the function?
Is there a way to get the class type with type parameters inserted from the runtime type information available in the function?
classOf[Bar[T]] works for a very simple reason: it doesn't insert any runtime information! classOf[Bar[T]], classOf[Bar[String]], classOf[Bar[Int]], classOf[Bar[_]] are all the same; that's what type erasure means in JVM context (to avoid misleading, I prefer always using classOf[Bar[_]] where possible). Note that there is actually a single exception: if Bar is Array, because classOf[Array[Int]] and classOf[Array[Object]] (e.g.) are different!
classOf[T] obviously would need runtime information and so it doesn't work.
Thanks to the comment by #Mr. V I realized that its actually easier than I initially thought:
import scala.reflect.runtime.universe._
class Bar[T]
def foo[T]() {
val clazz = classOf[Bar[T]]
}
Suppose I have:
class X
{
val listPrimitive: List[Int] = null
val listX: List[X] = null
}
and I print out the return types of each method in Scala as follows:
classOf[ComplexType].getMethods().foreach { m => println(s"${m.getName}: ${m.getGenericReturnType()}") }
listPrimitive: scala.collection.immutable.List<Object>
listX: scala.collection.immutable.List<X>
So... I can determine that the listX's element type is X, but is there any way to determine via reflection that listPrimitive's element type is actually java.lang.Integer? ...
val list:List[Int] = List[Int](123);
val listErased:List[_] = list;
println(s"${listErased(0).getClass()}") // java.lang.Integer
NB. This seems not to be an issue due to JVM type erasure since I can find the types parameter of List. It looks like the scala compiler throws away this type information IFF the parameter type is java.lang.[numbers] .
UPDATE:
I suspect this type information is available, due to the following experiment. Suppose I define:
class TestX{
def f(x:X):Unit = {
val floats:List[Float] = x.listPrimitive() // type mismatch error
}
}
and X.class is imported via a jar. The full type information must be available in X.class in order that this case correctly fails to compile.
UPDATE2:
Imagine you're writing a scala extension to a Java serialization library. You need to implement a:
def getSerializer(clz:Class[_]):Serializer
function that needs to do different things depending on whether:
clz==List[Int] (or equivalently: List[java.lang.Integer])
clz==List[Float] (or equivalently: List[java.lang.Float])
clz==List[MyClass]
My problem is that I will only ever see:
clz==List[Object]
clz==List[Object]
clz==List[MyClass]
because clz is provided to this function as clz.getMethods()(i).getGenericReturnType().
Starting with clz:Class[_] how can I recover the element type information that was lost?
Its not clear to me that TypeToken will help me because its usages:
typeTag[T]
requires that I provide T (ie. at compile time).
So, one path to a solution... Given some clz:Class[_], can I determine the TypeTokens of its method's return types? Clearly this is possible as this information must be contained (somewhere) in a .class file for a scala compiler to correctly generate type mismatch errors (see above).
At the java bytecode level Ints have to be represented as something else (apparently Object) because a List can only contain objects, not primitives. So that's what java-level reflection can tell you. But the scala type information is, as you infer, present (at the bytecode level it's in an annotation, IIRC), so you should be able to inspect it with scala reflection:
import scala.reflect.runtime.universe._
val list:List[Int] = List[Int](123)
def printTypeOf[A: TypeTag](a: A) = println(typeOf[A])
printTypeOf(list)
Response to update2: you should use scala reflection to obtain a mirror, not the Class[_] object. You can go via the class name if need be:
import scala.reflect.runtime.universe._
val rm = runtimeMirror(getClass.getClassLoader)
val someClass: Class[_] = ...
val scalaMirrorOfClass = rm.staticClass(someClass.getName)
// or possibly rm.reflectClass(someClass) ?
val someObject: Any = ...
val scalaMirrorOfObject = rm.reflectClass(someObject)
I guess if you really only have the class, you could create a classloader that only loads that class? I can't imagine a use case where you wouldn't have the class, or even a value, though.
Let's consider this code:
class A
object A{
implicit def A2Int(implicit a:A)=1
implicit def A2String(a:A)="Hello"
}
object Run extends App{
implicit val a: A =new A
import A.A2Int
// without this import this code does not compile, why ?
// why is no import needed for A2String then ?
def iWantInt(implicit i:Int)=println(i)
def iWantString(implicit s:String)=println(s)
iWantInt
iWantString(a)
}
It runs and prints:
1
Hello
Now, if we comment out the line
import A.A2Int
then we get a compilation error:
With the line commented out, why Scala cannot find A.A2String if it can find A.A2Int ?
How can this problem be fixed ?
Thanks for reading.
The difference is that when you do iWantString(a), the compiler gets some starting point to work from: you are explicitly passing a, which the compiler knows is of type A.
Given that iWantString takes a String and not an A, the compiler will search for an implicit conversion from A to String in order to insert it and make the call succeed.
Implicit lookup rules state that the compiler must look (among other places) in the companion object of class A because type A is the source type of the conversion.
This is where it finds the implicit conversion A2String.
What you must get from this is that it is only because you passed an instance of A that the compiler knew to look for implicit conversions into the companion object of A.
When you just do iWantInt, the compiler has no reason to look into A, so it won't find your method A2Int (and as no other method/value in scope provides an implicit value of type Int, compilation then fails).
For more information about implicit lookup rules, see the
See the scala specification at http://www.scala-lang.org/docu/files/ScalaReference.pdf (chapter 7.2). Here's the most relevant excerpt:
The implicit scope of a type T consists of all companion modules (§5.4) of classes
that are associated with the implicit parameter’s type.
The following code fails for me:
object Message {
def parse[T](bsonDoc: BSONDocument): Try[T] = {
implicit val bsonHandler = Macros.handler[T]
bsonDoc.seeAsTry[T]
}
}
Message.parse[messages.ClientHello](data)
The error is:
No apply function found for T
implicit val bsonHandler = Macros.handler[T]
^
However, if I hardcode a type (one of my case classes), it's fine:
object Message {
def parse(bsonDoc: BSONDocument): Try[ClientHello] = {
implicit val bsonHandler = Macros.handler[ClientHello]
bsonDoc.seeAsTry[ClientHello]
}
}
Message.parse(data)
So I presume this is a problem using generics. Incidentally, I have to import messages.ClientHello. If I just use messages.ClientHello I get:
not found: value ClientHello
implicit val bsonHandler = Macros.handler[messages.ClientHello]
^
How can I achieve what I'm trying to do, which is to have a single method that will take a BSON document and return an instance of the appropriate case class?
1) Macro applications get expanded immediately when encountered (well, modulo some fine details of type inference that are irrelevant here). This means that when you write handler[T], handler will try to expand with T as a type parameter. This won't lead to anything good, hence the error. To make this work, you need to turn Message.parse into a macro itself.
2) This happens because ReactiveMongo macros are unhygienic. Specifically, https://github.com/ReactiveMongo/ReactiveMongo/blob/v0.10.0/macros/src/main/scala/macros.scala#L142 isn't going to work correctly in situations like yours, because it uses simple name of the class, not a fully qualified name. I think the best way to make the macro work correctly would be using Ident(companion), not Ident(companion.name) - that would ensure that this identifier binds to the companion, not to something in scope having the same name.
I have an interface defined using a structural type like this:
trait Foo {
def collection: {
def apply(a: Int) : String
def values() : collection.Iterable[String]
}
}
}
I wanted to have one of the implementers of this interface do so using a standard mutable HashMap:
class Bar {
val collection: HashMap[Int, String] = HashMap[Int, String]()
}
It compiles, but at runtime I get a NoSuchMethod exception when referring a Bar instance through a Foo typed variable. Dumping out the object's methods via reflection I see that the HashMap's apply method takes an Object due to type erasure, and there's some crazily renamed generated apply method that does take an int. Is there a way to make generics work with structural types? Note in this particular case I was able to solve my problem using an actual trait instead of a structural type and that is overall much cleaner.
Short answer is that the apply method parameter is causing you grief because it requires some implicit conversions of the parameter (Int => Integer). Implicits are resolved at compile time, the NoSuchMethodException is likely a result of these missing implicits.
Attempt to use the values method and it should work since there are no implicits being used.
I've attempted to find a way to make this example work but have had no success so far.