How to getClass implicitly - scala

I'm writing a Scala wrapper over some Java code with a method signature like method(cl: Class[_], name: String) and many getClass methods in code looks not good:
Creator.create(getClass, "One")
Creator.create(getClass, "Two")
Creator.create(getClass, "Three")
Creator.create(getClass, "Four")
So can we somehow get enclosing class implicitly like Creator.create("some name")?

Answer 1.
In general I warmly discourage reflection. However, if you really want to do it, in Scala 2.9.1 you can use Manifest
def create[T:Manifest](name:String) = {
val klass:Class[_] = t.erasure
}
In scala 2.10 you should have a look to TypeTag.
Answer 2.
However, as I already said, the right approach would not be to use class but implicit builders
trait Builder[T]{
def build(name:String):T
}
def create[T](name:String)(implicit builder:Builder[T]) = {
builder.build(name)
}
in that way you can limit what you can create by importing only the right implicits in scope, you won't rely on reflection and you won't risk to get horrible RuntimeExceptions
Post comment answer
If your point is to avoid calling getClass at each invocation, you can do the following
def create(name:String)(implicit klass:Class[_]) {
}
And you can call it this way
implicit val klass1 = myInstance.getClass
create("hello")
create("goodbye")

Related

How to get reflected runtime Method from AnyRef object?

I am trying to get the reflected runtime method in an instance but it is not shown in the decls result:
val foo: AnyRef = new Object {
def bar = 1
}
typeOf[foo.type].decls //Does not contain bar method
I tried to use Java reflection class and it works:
foo.getClass.getDeclaredMethods //It contains bar method
But I prefer to work with MethodSymbols and Scala Type than Java Class and Method reflection. How can I get the reflected MethodSymbol?
I want an method to look up an object passed as AnyRef for a method bar and call it. Something like below:
def getBarMethodFromObj(obj: AnyRef): MethodSymbol = {
//typeOf(obj).decl(TermName("bar")) this doesn't work
}
I cannot use trait because bar can have different argument and return types and numbers. As Scala does not support varadic generic arguments, I plan to use reflection to find the method and call, but this cannot be done in Scala as well. I am currently use Java solution:
val bar = foo.getClass.getDeclaredMethods.find(_.getName == "bar")
bar.invoke(foo, params: _*)
However Java reflection does not retain generic types as it creates problem for List and Map, etc. So I want to know if I can implement this in Scala, or is there any coming solution
I don't know what you're trying to do, but removing the AnyRef annotation makes your code work:
val foo = new { def bar = 1 }
typeOf[foo.type].decls // Contains bar method
If you need a type annotation (for example, in a method signature), you can use the same structural type that the compiler infers:
val foo: { def bar: Int } = new { def bar = 1 }
If you want to get the full list of methods from another method without knowing the exact type except via generics, you may be interested in TypeTag:
import scala.reflect.runtime.universe.{ TypeTag, typeTag }
val foo = new { def bar = 1 }
def getMethods[T: TypeTag](t: T) = typeTag[T].tpe.decls
getMethods(foo) // Contains bar
If you can't use TypeTag (maybe because you can't make API changes), then you're probably best off using the Java reflection API. The Scala reflection API is generally designed to use type information, so it may not work for you if you only know the type is AnyRef.
In response to your edit:
I cannot use trait because bar can have different argument and return types and numbers.
Sure you can:
trait Foo[A, B] {
def bar(a: A): B
}
If you need multiple arguments, just have bar take a tuple instead. If you need to do some list manipulation that tuples don't support, you might consider learning about HLists and shapeless.
However Java reflection does not retain generic types...
Well, no runtime-only reflection API will help you there. There is simply no way to find out what generic parameters an AnyRef has at runtime, as that information doesn't exist on the JVM. Use TypeTags, or use a trait in the manner described above.

How to mock scala generic method

I have a traits(below simple versions) and I want to mock Foo.
trait MyTrait[A]
trait Foo {
def bar[T: MyTrait](id:Int, data: T, other:Option[String] = None): String
}
I tried:
implicit val myTrait = new MyTrait[String] {}
val src = mock[Foo]
when(src.bar(any(),any(),any())).thenReturn("ok")
src.bar(1, "some", None)
It fails with:
Invalid use of argument matchers! 4 matchers expected, 3 recorded
How to mock this kind of method?
Mockito does not play well with scala code. What happens in your case is that
notify.bar(any(), any(), any()) has to be invoked inside when(), but type of the bar method is unknown, so when scalac is looking-up implicits there are possibly several instances of Writes that fit here (becuase all of them do).
You can do something like this to make it work:
when(src.bar[T](any(),any(),any())).thenReturn("ok")
Edit
Following your edit, i think you should reconsider usage of mockito in the first place. Here's what happens:
Foo has the following signature after desugaring
trait Foo {
def bar[T](id:Int, data: T, other:Option[String] = None)(implicit ev: MyTrait[T]): String
}
I don't know if you are aware how does mockito work, but here is a quick explanation why (from what i can tell) this error happens:
at runtime method bar has the following "signature" (due to type erasure):
bar(id: Int, data: Object, other: Option[Object], ev: MyTrait[Object])
when(src.bar[T](any(),any(),any())).thenReturn("ok") actually invokes this method on a proxy object and registers "matchers", but ev is passed myTrait instead of a matcher, so i guess this violates some constraints of the library
As side-note: usually mocking is not that hard and you can simply implement a "mocked" trait without any help from mockito or other similar library.
The syntax [T : MyTrait] is sugar to add (implicit typeClass: MyTrait[T]) as a second set of arguments, so basically you're missing an argument matcher as the error states
So if you do
val src = mock[Foo]
when(src.bar(any(),any(),any())(any())).thenReturn("ok")
it works as expected
BTW, this is a bit of self promotion but I just published a library called mockito-scala that improves the mockito syntax for Scala, is part of the mockito ecosystem so hopefully should become the default when working with Scala, you can find it here https://github.com/mockito/mockito-scala with the information to get the dependency and what problems does it actually solves.

Can structural typing work with generics?

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.

How to test type conformance of higher-kinded types in Scala

I am trying to test whether two "containers" use the same higher-kinded type. Look at the following code:
import scala.reflect.runtime.universe._
class Funct[A[_],B]
class Foo[A : TypeTag](x: A) {
def test[B[_]](implicit wt: WeakTypeTag[B[_]]) =
println(typeOf[A] <:< weakTypeOf[Funct[B,_]])
def print[B[_]](implicit wt: WeakTypeTag[B[_]]) = {
println(typeOf[A])
println(weakTypeOf[B[_]])
}
}
val x = new Foo(new Funct[Option,Int])
x.test[Option]
x.print[Option]
The output is:
false
Test.Funct[Option,Int]
scala.Option[_]
However, I expect the conformance test to succeed. What am I doing wrong? How can I test for higher-kinded types?
Clarification
In my case, the values I am testing (the x: A in the example) come in a List[c.Expr[Any]] in a Macro. So any solution relying on static resolution (as the one I have given), will not solve my problem.
It's the mixup between underscores used in type parameter definitions and elsewhere. The underscore in TypeTag[B[_]] means an existential type, hence you get a tag not for B, but for an existential wrapper over it, which is pretty much useless without manual postprocessing.
Consequently typeOf[Funct[B, _]] that needs a tag for raw B can't make use of the tag for the wrapper and gets upset. By getting upset I mean it refuses to splice the tag in scope and fails with a compilation error. If you use weakTypeOf instead, then that one will succeed, but it will generate stubs for everything it couldn't splice, making the result useless for subtyping checks.
Looks like in this case we really hit the limits of Scala in the sense that there's no way for us to refer to raw B in WeakTypeTag[B], because we don't have kind polymorphism in Scala. Hopefully something like DOT will save us from this inconvenience, but in the meanwhile you can use this workaround (it's not pretty, but I haven't been able to come up with a simpler approach).
import scala.reflect.runtime.universe._
object Test extends App {
class Foo[B[_], T]
// NOTE: ideally we'd be able to write this, but since it's not valid Scala
// we have to work around by using an existential type
// def test[B[_]](implicit tt: WeakTypeTag[B]) = weakTypeOf[Foo[B, _]]
def test[B[_]](implicit tt: WeakTypeTag[B[_]]) = {
val ExistentialType(_, TypeRef(pre, sym, _)) = tt.tpe
// attempt #1: just compose the type manually
// but what do we put there instead of question marks?!
// appliedType(typeOf[Foo], List(TypeRef(pre, sym, Nil), ???))
// attempt #2: reify a template and then manually replace the stubs
val template = typeOf[Foo[Hack, _]]
val result = template.substituteSymbols(List(typeOf[Hack[_]].typeSymbol), List(sym))
println(result)
}
test[Option]
}
// has to be top-level, otherwise the substituion magic won't work
class Hack[T]
An astute reader will notice that I used WeakTypeTag in the signature of foo, even though I should be able to use TypeTag. After all, we call foo on an Option which is a well-behaved type, in the sense that it doesn't involve unresolved type parameters or local classes that pose problems for TypeTags. Unfortunately, it's not that simple because of https://issues.scala-lang.org/browse/SI-7686, so we're forced to use a weak tag even though we shouldn't need to.
The following is an answer that works for the example I have given (and might help others), but does not apply to my (non-simplified) case.
Stealing from #pedrofurla's hint, and using type-classes:
trait ConfTest[A,B] {
def conform: Boolean
}
trait LowPrioConfTest {
implicit def ctF[A,B] = new ConfTest[A,B] { val conform = false }
}
object ConfTest extends LowPrioConfTest {
implicit def ctT[A,B](implicit ev: A <:< B) =
new ConfTest[A,B] { val conform = true }
}
And add this to Foo:
def imp[B[_]](implicit ct: ConfTest[A,Funct[B,_]]) =
println(ct.conform)
Now:
x.imp[Option] // --> true
x.imp[List] // --> false

Scala and Python's pass

I was wondering, is there an equivalent of python's pass expression? The idea is to write method signatures without implementations and compiling them just to type-check those signatures for some library prototyping. I was able to kind of simulate such behavior using this:
def pass[A]:A = {throw new Exception("pass"); (new Object()).asInstanceOf[A]}
now when i write:
def foo():Int = bar()
def bar() = pass[Int]
it works(it typechecks but runtime explodes, which is fine), but my implementation doesn't feel right (for example the usage of java.lang.Object()). Is there better way to simulate such behavior?
In Scala 2.10, there is the ??? method in Predef.
scala> ???
scala.NotImplementedError: an implementation is missing
at scala.Predef$.$qmark$qmark$qmark(Predef.scala:252)
...
In 2.9, you can define your own one like this:
def ???[A]:A = throw new Exception("not implemented")
If you use this version without an explicit type paramter, A will be inferred to be Nothing.