Scala: Cast to a runtime Class instance - scala

See the following code snippet:
def getObject(key: String, cacheName: String)(clazz: Class[_ <: ICacheable]) = {
Option(icacheFactory.getCache(cacheName).get(key).asInstanceOf[clazz])
}
The compiler complains about the asInstanceOf[clazz]
Basically what I am trying to do is to cast the ICacheable returned from icacheFactory.getCache(cacheName).get(key) to an instance of clazz
How do I go about this? It seems that asInstanceOf only supports static types

The closest to your solution is
def getObject(key: String, cacheName: String)(clazz: Class[_ <: ICacheable]) =
Try(clazz.cast(icacheFactory.getCache(cacheName).get(key)))
(see Class javadoc for cast). If you know the class you want at the compilation time instead of receiving it from outside (e.g. as string or as Class from client code), you can avoid passing the classes explicitly by using ClassTags:
def getObject[T <: ICacheable](key: String, cacheName: String)(implicit tag: ClassTag[T]) =
Try(tag.runtimeClass.cast(icacheFactory.getCache(cacheName).get(key)))
You call it as follows:
getObject[SomeCacheable](key, cacheName)
For the first version:
getObject(key, cacheName)(classOf[SomeCacheable])

Straight brackets, "[]", indicate a type parameter - you must supply asInstanceOf with a type, not a value like clazz. Also, asInstanceOf never returns null, instead it throws an exception if the cast isn't possible, so wrap it in Try rather than Option. Here is a rewritten version of your function:
def getObject[A <: ICacheable](key: String, cacheName: String) = {
Try(icacheFactory.getCache(cacheName).get(key).asInstanceOf[A])
}
Unlike Java code with the hideous need to pass around Class objects, in Scala type inference might make it completely unnecessary to even specify the type parameter:
def f(x: SubclassOfICacheable) = ???
getObject("cache", "key") map f
Scala can infer that A should be SubclassOfICacheable without needing it explicitly specified.

Related

Getting name of parameterized class in scala using shapeless

I want to get the name of a class passed as a parameter to a function using shapeless. I've tried this:
def sayMyName[T](t: T): String = Typeable[T].describe // error: class type required but T found
If T is replaced with a concrete type, there's no problem. Is it possible to make something like this work using shapeless?
You just need to add Typeable typeclass as context bound of your type T:
def sayMyName[T: Typeable](t: T): String = Typeable[T].describe
sayMyName("") //String
You could also explicitly declare implicit parameter:
def sayMyName[T](t: T)(implicit typeable: Typeable[T]): String = Typeable[T].describe
By adding context bound you're asking the compiler to wait with resolving Typeable
typeclass until sayMyName is called with the concrete type, not resolve it right away (which is impossible, since the real type of T is not yet known at this point).

Implicit conversions weirdness

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.

Scala function arguments: class vs function generic type, e.g. f(classOf[Foo], "bar") vs f[Foo]("bar")

In Scala is it common practice to pass in class types as generics or explicitly pass them in?
For example I have created a helper function to create a Java object that takes in a source exception, target exception and a third parameter (I'll just use a String for this example). Which one is better practice in Scala:
exceptionTranslation(classOf[FooException], classOf[BarException], "blah")
def exceptionTranslation(sourceClazz: Class[_ <: Throwable], targetClazz: Class[_ <: Throwable], message: String) = new Translation()
.withSource(sourceClazz)
.withTarget(targetClazz)
.withMessage(message)
Or
exceptionTranslation[FooException, BarException]("blah")
def exceptionTranslation[Source <: Throwable, Target <: Throwable](message: String)(
implicit source: ClassTag[Source], target: ClassTag[Target]) = new Translation()
.withSource(source.runtimeClass.asInstanceOf[Class[Source]])
.withTarget(target.runtimeClass.asInstanceOf[Class[Target]])
.withMessage(message)
I think is just a matter of style. They are all correct. Personally, I would go with the one that is more intuitive, shorter, and has the least power.
Example of extracting the text name of a class:
import scala.reflect._
def bar[F](x: Class[F]) = x.getName
def foo[X:ClassTag] = implicitly[ClassTag[X]].runtimeClass.getName
def foobar[X](implicit ctag: ClassTag[X]) = ctag.runtimeClass.getName
Usage:
> bar(classOf[Double]) // This one has better Java interop
res: String = "double"
> foo[Double] // This looks slightly less verbose when calling
res: String = "double"
> foobar[Double]
res: String = "double"

Scala - how to create a single implicit that can be used for a type constructor

I'm trying to write a method which uses the isEmpty method on types String, Option and List. These classes don't share a common base trait with that method, so I've tried to pass an implicit EmptyChecker in with them:
trait EmptyChecker[Field] {
def isEmpty(data: Field): Boolean
}
implicit val StringEmptyChecker: EmptyChecker[String] = new EmptyChecker[String] {
def isEmpty(string: String): Boolean = string.isEmpty
}
def printEmptiness[Field](field: Field)(implicit emptyChecker: EmptyChecker[Field]): Unit = {
if (emptyChecker.isEmpty(field))
println("Empty")
else
println("Not empty")
}
printEmptiness("abc") // Works fine
The String empty checker works fine, but I've hit problems with making empty checkers for type constructors like Option and List.
For example, Option doesn't work:
implicit val OptionChecker: EmptyChecker[Option[_]] = new EmptyChecker[Option[_]] {
def isEmpty(option: Option[_]): Boolean = option.isEmpty
}
// Both fail compilation: "could not find implicit value for parameter emptyChecker: EmptyChecker[Some[Int]]
printEmptiness(Some(3))
printEmptiness[Option[Int]](Some(3))
If I use a specific Option[Int] checker, it works a little better, but is a bit ugly:
implicit val OptionIntChecker: EmptyChecker[Option[Int]] = new EmptyChecker[Option[Int]] {
def isEmpty(optionInt: Option[Int]): Boolean = optionInt.isEmpty
}
// Fails like above:
printEmptiness(Some(3))
// Passes compilation:
printEmptiness[Option[Int]](Some(3))
So my question is: is it possible to make a single EmptyChecker for each Option and List type and have them work with my method without needing to explicitly declare the type whenever I call it? I'm trying to get a type safe duck typing effect.
I'm using scala 2.11.6.
Thanks in advance!
The source of your problem is that the type of Some(1) is Some[Int], not Option[Int]. There are a couple of ways around this; you can explicitly upcast the expression with a type ascription: printEmptiness(Some(3): Option[Int]). Alternatively, you can define a helper method to do this for you automatically, and if you're using Scalaz, there's one of these provided:
import scalaz.syntax.std.option._
printEmptiness(3.some)
Furthermore if you do use Scalaz, you may find looking at the PlusEmpty/ApplicativePlus/MonadPlus type classes useful.

F-Bounded Polymorphic return types in Scala?

I'm going crazy trying to make F-Bounded Polymorphism work as I want in Scala.
The following code will not compile:
object TestTypeBounds {
trait Upper[T <: Upper[T]] {
def map() : T
}
class Impl extends Upper[Impl] {
def map() : Impl = this
}
type Arr = Upper[T] forSome {type T <: Upper[T]}
def testBounds() {
// Though any is specified as the type parameter, the definition of Upper specifies
// an upper bound of Upper
val upper: Upper[_] = new Impl()
// This must 'logically' be an Upper, but the compiler thinks it's an Any
val mapped = upper.map()
// This line will fail!
mapped.map().map().map()
}
def main(args: Array[String]): Unit = {
testBounds()
}
}
The problem here is that the compiler complains that the type of mapped is Any, and therefore it has no method map. It's not clear to me why the compiler does not assign mapped the type Upper since this is in fact the upper type bound of the parameter type of Upper, even if any was specified in this instance.
Note that replacing the type of "val upper...:" with the alias Arr would work, because now Scala can see that the type is recursive and will always be an Upper. Unfortunately, this approach does also not work for me because I am implementing a Java library which passes Upper[_] arguments to functions, and these then run into the above problem. The compiler also does not accept code where such functions are overridden as having "Arr" arguments, i.e. the alias does not work in that scenario.
Edit: The final paragraph is not entirely correct, see my answer below
As #Rado Buransky pointed out, you cannot just omit the type constructor parameter by using an underscore. The following works for example:
def testBounds[T <: Upper[T]](make: => T): Unit = {
val upper: T = make
val mapped = upper.map()
mapped.map().map().map()
}
testBounds(new Impl)
Also this, using an existential type:
def testBounds: Unit = {
val upper: Upper[T] forSome { type T <: Upper[T] } = new Impl
val mapped = upper.map()
mapped.map().map().map()
}
My view on this is that you should not use underscore "_". It tells the compiler that you don't care about the type parameter. But you do. I know that there is the upper bound, but probably there is an optimization which makes the compiler really don't care.
Just a hint, sometimes, for me, if nothing works, there is always the asInstanceOf[T] method. Maybe this helps you:
def giveMeUpper[T <: Upper[T]] = (new Impl).asInstanceOf[Upper[T]]
...
val upper = giveMeUpper[Impl]
In terms of the 'pure' Scala part of the question, 0__ is correct and I have accepted his answer.
Regarding the Java Part: It turns out that if a Java function returns Upper and the Upper interface is defined in Java equivalently to the Scala implementation above, then the compiler does in fact correctly assign it the type Upper[_$2] forSome {type $2 <: Upper[$2]} - i.e. it interoperates correctly. The final problem I had was in fact caused by implicit functions defined in Scala that still returned Upper[_]. Mea Culpa.