cannot find class manifest for element type T - scala

Was trying to compile some code from this SO question and run into this error message cannot find class manifest for element type T. Here is another snippet that shows the behavior:
scala> def f[T](a:T, b:T):Array[T] = { new Array[T](2) }
<console>:4: error: cannot find class manifest for element type T
def f[T](a:T, b:T):Array[T] = { new Array[T](2) }
I can see that new collection.mutable.GenericArray[T](2) fixes the issue. Apparently providing a manifest is the other option... But what does "providing a manifest mean"?

To provide type information you can use a context bound
def f[T : Manifest](a:T, b:T):Array[T] = { new Array[T](2) }
or the manifest as an implicit argument:
def f[T](a:T, b:T)(implicit manifest : Manifest[T]) : Array[T] = { new Array[T](2) }
The former is syntactic sugar for the later. The manifest is needed because the type information about T is missing due to generic type errasure of the JVM.

Related

Scala Dynamic Parse Json using case class No Manifest available for T

I have a JSON string and I created a function which parses this JSON as an object using Scala case class. I wrote the below code to parse it in a generic way. However, It gave me an error:
def getJsonObj[T](jsonString:String): T = {
implicit val formats: DefaultFormats.type = DefaultFormats
parse(jsonString).extract[T]
}
Error can be found below:
Error:(19, 32) No Manifest available for T.
parse(jsonString).extract[T] Error:(19, 32) not enough arguments for
method extract: (implicit formats: org.json4s.Formats, implicit mf:
scala.reflect.Manifest[T])T. Unspecified value parameter mf.
parse(jsonString).extract[T]
I found this No Manifest available for Type But I don't know how to fix it in my code. Also, I found this,Spark Scala - How to construct Scala Map from nested JSON (Scala: "No manifest available for type T") But I need to pass the case class to the function in a generic way. It seems a common problem but I can't solve it using the available answers as I am new in Scala.
Another point, How can I add try-catch to see if it's correctly parsed or not?
I think this answer solves your question, Scala: “No manifest available for type T”. It easily solved by implicitly passing on the manifest for the type method. I add an example of the code and a simple function for error handling.
val jsonStr: String = """{"airports":[{"name":"sfo","score":1},{"name":"phx","score":1},{"name":"sjc","score":1}]}"""
case class AirPortScores(name: String, score: Double)
case class JsonRulesHandler(airports: List[AirPortScores])
val json: JsonRulesHandler = getJsonObj[JsonRulesHandler](jsonStr)
println(json)
def getJsonObj[T](jsonString:String)(implicit m: Manifest[T]): T = {
extractFrom(jsonString) match {
case Success(jsonParsed) ⇒
jsonParsed
case Failure(exc) ⇒
throw new IllegalArgumentException(exc)
}
}
private def extractFrom[T](jsonString:String)(implicit m: Manifest[T]): Try[T] = {
implicit val formats: DefaultFormats.type = DefaultFormats
Try {
parse(jsonString).extract[T]
}
}

Collection structural type parameter weirdness

This seems like a simple thing but I can't understand it...
This compiles:
object CanFoo1 {
def foo(): Unit = {
println("Yup, I can foo alright")
}
}
object CanFoo2 {
def foo(): Unit = {
println("And I can foo with the best")
}
}
trait A {
type CanFoo = { def foo(): Unit }
def fooers: Seq[CanFoo]
}
class B extends A {
def fooers = Seq(
// CanFoo1, // <- won't compile when this is uncommented
CanFoo2
)
}
But uncommenting the // CanFoo1, line gives:
error: type mismatch;
found : Seq[Object]
required: Seq[B.this.CanFoo]
(which expands to) Seq[AnyRef{def foo(): Unit}]
def fooers = Seq(
^
one error found
So it seems like the compiler understands that a collection containing just one element Seq(CanFoo2) (or Seq(CanFoo1)) is of the correct type, but when both objects are in the collection it gives up? What am I doing wrong here?
So it seems like the compiler understands that a collection containing
just one element Seq(CanFoo2) (or Seq(CanFoo1)) is of the correct
type, but when both objects are in the collection it gives up? What am
I doing wrong here?
When you pass CanFoo1 or CanFoo2 to the Seq apply, the sequence is inferred to be of type CanFoo1.type or CanFoo2.type respectively, it is not inferred to be of type CanFoo.
When you pass in both elements to the Seq, the compiler tries to look for a common type to which it can validly infer to make the code compile, and the only type it can find is Object, but fooers is said to be of type Seq[CanFoo], so the compiler yells.
You can help the compiler a little by explicitly writing the type of the collection:
class B extends A {
def fooers = Seq[CanFoo](
CanFoo1,
CanFoo2
)
}

Passing a type parameter for instantiation

Why wouldn't the scala compiler dig this:
class Clazz
class Foo[C <: Clazz] {
val foo = new C
}
class type required but C found
[error] val a = new C
[error] ^
Related question - How to get rid of : class type required but T found
This is a classic generic problem that also happens in Java - you cannot create an instance of a generic type variable. What you can do in Scala to fix this, however, is to introduce a type evidence to your type parameter that captures the runtime type:
class Foo[C <: Clazz](implicit ct: ClassTag[C]) {
val foo = ct.runtimeClass.newInstance
}
Note that this only works if the class has a constructor without any arguments. Since the parameter is implicit, you don't need to pass it when calling the Foo constructor:
Foo[Clazz]()
I came up with this scheme, couldn't simplify it through a companion object thought.
class Clazz
class ClazzFactory {
def apply = new Clazz
}
class Foo(factory: ClazzFactory) {
val foo: Clazz = factory.apply
}
It's very annoying that ClazzFactory can't be an object rather than a class though. A simplified version:
class Clazz {
def apply() = new Clazz
}
class Foo(factory: Clazz) {
val foo: Clazz = factory.apply
}
This requires the caller to use the new keyword in order to provide the factory argument, which is already a minor enough annoyance relative to the initial problem. But, scala could have made this scenario all more elegant; I had to fallback here to passing a parameter of the type I wish to instantiate, plus the new keyword. Maybe there's a better way.
(motivation was to instantiate that type many times within the real Foo, that's why this is at all a solution; otherwise my pattern above is just redundantly meaningless).

Scala compiler error on wildcard Array with val

The following code fails when the constructor parameter is declared with val
Works:
class Poso(array : Array[_ <: Any])
object Test {
new Poso(classOf[Retention].getEnumConstants())
}
Doesn't work:
class Poso(val array : Array[_ <: Any])
object Test {
new Poso(classOf[Retention].getEnumConstants())
}
The compiler gives the error:
Error in Scala compiler: type mismatch; found :java.lang.Object required: array[java.lang.Object]
Without being able to give a line number.
Looks like a bug in Scala compiler (it dies on an exception). You should probably report it to Scala developers.
Using AnyRef instead of Any fixed it for me:
class Poso(val array : Array[_ <: AnyRef])
object Test {
new Poso(classOf[java.lang.annotation.Retention].getEnumConstants())
}

Why is the Manifest not available in the constructor?

Consider this code:
class Foo[T : Manifest](val id: String = manifest[T].erasure.getName)
I basically want to store an identifier in Foo, which is often just the class name.
Subclass which do not need a special identifier could then easily use the default value.
But this doesn't even compile, the error message is:
error: No Manifest available for T.
Is there another approach which will work?
EDIT:
Why does this work if the manifest isn't available until the primary constructor?
class Foo[T: Manifest](val name: String) {
def this() = this(manifest[T].erasure.getName)
}
When the syntactic sugar is removed from that context bound, it gets rewritten as:
class Foo[T]
(val id: String = implicitly[Manifest[T]].erasure.getName)
(implicit ev$1: Manifest[T]) = ...
So the Manifest evidence simply isn't available when determining the default value of id. I'd instead write something like this:
class Foo[T : Manifest](id0: String = "") {
val id = if (id0 != "") id0 else manifest[T].erasure.getName
}
In your second approach (which is a great solution, by the way!), expect a rewrite similar to:
class Foo[T](val name: String)(implicit x$1: Manifest[T]) {
def this()(implicit ev$2: Manifest[T]) = this(manifest[T].erasure.getName)
}
So yes, the manifest is available before the call to manifest[T].erasure