Consider the case that I want to deserialize a JSON string:
def deserialize[T](json)
I can provided class that I want to apply the function explicitly while writing code like
class Person(name: String)
deserialize[Person]("""{ "name": "Jennie" }""")
But, what if I need other class, I have to provide it in my code, compile again. I want my program more flexible, it can take a config file that contains name of which class I want to use. So, when ever require a new class, I just need to write the class definition, build it into another jar file, put it in classpath, then restart the program.
val config = ConfigLoader.load("config.txt")
val className = config.getString("class-to-deserialize")
deserialize[<from className to type>](json)
So, is it possible to do that in scala?
No. But because of type erasure, if you have a function def deserialize[T](json: String), its behavior can't depend on T in the first place and it doesn't matter what you pass as the type parameter. You may just need to add a cast at the end.
What is possible is to write such a function which also accepts an implicit ClassTag or TypeTag parameter, in which case you just need to create the parameter from class/type name, and that's entirely possible: just search for questions about this.
Related
How can you make code in a Scala library call type-specific code for objects supplied by a caller to that library, where the decision about which type-specific code to call is made at compile-time (statically), not at run-time?
To illustrate the concept, suppose I want to make a library function that prints objects one way if there's a CanMakeDetailedString defined for them, or just as .toString if not. See nicePrint in this example code:
import scala.language.implicitConversions
trait CanMakeDetailedString[A] extends (A => String)
def noDetailedString[A] = new CanMakeDetailedString[A] {
def apply(a: A) = a.toString
}
object Util {
def nicePrint[A](a: A)
(implicit toDetail: CanMakeDetailedString[A] = noDetailedString[A])
: Unit = println(toDetail(a))
def doStuff[A](a: A)
: Unit = { /* stuff goes here */ nicePrint(a) }
}
Now here is some test code:
object Main {
import Util._
case class Rototiller(name: String)
implicit val rototillerDetail = new CanMakeDetailedString[Rototiller] {
def apply(r: Rototiller) = s"The rototiller named ${r.name}."
}
val r = Rototiller("R51")
nicePrint(r)
doStuff(r)
}
Here's the output in Scala 2.11.2:
The rototiller named R51.
Rototiller(R51)
When I call nicePrint from the same scope where rototillerDetail is defined, the Scala compiler finds rototillerDetail and passes it implicitly to nicePrint. But when, from the same scope, I call a function in a different scope (doStuff) that calls nicePrint, the Scala compiler doesn't find rototillerDetail.
No doubt there are good reasons for that. I'm wondering, though, how can I tell the Scala compiler "If an object of the needed type exists, use it!"?
I can think of two workarounds, neither of which is satisfactory:
Supply an implicit toDetail argument to doStuff. This works, but it requires me to add an implicit toDetail argument to every function that might, somewhere lower in the call stack, have a use for a CanMakeDetailedString object. That is going to massively clutter my code.
Scrap the implicit approach altogether and do this in object-oriented style, making Rototiller inherit from CanMakeDetailedString by overriding a special new method like .toDetail.
Is there some technique, trick, or command-line switch that could enable the Scala compiler to statically resolve the right implicit object? (Rather than figuring it out dynamically, when the program is running, as in the object-oriented approach.) If not, this seems like a serious limitation on how much use library code can make of "typeclasses" or implicit arguments. In other words, what's a good way to do what I've done badly above?
Clarification: I'm not asking how this can be done with implicit val. I'm asking how you can get the Scala compiler to statically choose type-appropriate functions in library code, without explicitly listing, in every library function, an implicit argument for every function that might get called lower in the stack. It doesn't matter to me if it's done with implicits or anything else. I just want to know how to write generic code that chooses type-specific functions appropriately at compile-time.
implicits are resolved at compile time so it can't know what A is in doStuff without more information.
That information can be provided through an extra implicit parameter or a base type / interface as you suggested.
You could also use reflection on the A type, use the getType that returns the child type, cast the object to that type, and call a predefined function that has the name of the type that writes the string details for you. I don't really recommend it as any OOP or FP solution is better IMHO.
I am a newbie to scala.
Here is a Models.scala I am trying to write.
When I run sbt package it is giving error
Models.scala:25: models.Session.Network.type does not take parameters
[error] network : Network = Network() ,
I don't understand why this error is taking place, I am not passing any parameter in when doing Network(). Can someone please help me
Here is a smaller code that reproduces your problem :
case class A(b:B = B(3, 5))
case class B(i: Int, j: Int)
object A {
val B = "whatever"
}
On the first line, we get
too many arguments for method apply: (index: Int)Char in class StringOps
What happens is that when you define the signature of the case class, you are both defining the signature of the constructor (when you call with new), and of the apply method in the companion object (when you call without new).
When you put default value in argument, (Network() in your code, and B(3, 5) in mine), this code will be compiled both in the context of the constructor and of the apply method of the companion object.
As you have defined a companion object Session, the apply method is automatically added into this object. It happens that Network() in your companion object means Network.apply() on the Network object you have defined there, and it means the string B with value "whatever" in my code.
What is really weird then is that it is possible that the default expression has different meanings, but both correct in the context of the constructor and of the apply method. In this case, you may get different behavior depending on whether you call with or without new.
Here is an example :
case class A(b:B = bb)
case class B(i: Int, j: Int)
object bb extends B(3, 4)
object A {
val bb = new B(7, 2)
}
object Test extends App {
println(A())
println(new A())
}
Running test will print
A(B(7,2))
A(B(3,4))
For your specific problem, there are easy workarounds.
network: Network = models.Network(),
will work, obviously, because it is then clear that you want Network in the package and not in object Session.
network: Network = new Network(),
will work too, because with the new, the compiler will look for a Network type and not a Network value. In companion object session, the Network value is shadowed by the local declaration, but the Network type is not.
IMO, the former (models.Network) is clearer.
PS. I checked the specification and I believe this weird behavior is in line with it. Namely, (5.3.2) an apply method is genarated inside the companion object with the same parameter list as the constructor. That includes the default values, which would then be compiled inside the companion object.
It looks like you may have some import overrides going on. Do you have an import Sessions._ someplace in the code? Notice your error refers to Session.Network, which is your implicit BSonDocument class. You're probably trying to construct the plain case class.
Try using Network explicitly: network: models.Network = models.Network()
I have a function with the following signature:
myFunc[T <: AnyRef](arg: T)(implicit m: Manifest[T]) = ???
How can I invoke this function if I do not know the exact type of the argument at the compile time?
For example:
val obj: AnyRef = new Foo() // At compile time obj is defined as AnyRef,
val objClass = obj.getClass // At runtime I can figure out that it is actually Foo
// Now I would need to call `myFunc[Foo](obj.asInstanceOf[Foo])`,
// but how would I do it without putting [Foo] in the square braces?
I would want to write something logically similar to:
myFunc[objClass](obj.asInstanceOf[objClass])
Thank you!
UPDATE:
The question is invalid - As #DaoWen, #Jelmo and #itsbruce correctly pointed, the thing I was trying to do was a complete nonsense! I just overthought the problem severely.
THANK YOU guys! It's too bad I cannot accept all the answers as correct :)
So, the problem was caused by the following situation:
I am using Salat library to serialize the objects to/from BSON/JSON representation.
Salat has an Grater[T] class which is used for both serialization and deserialization.
The method call for deserialization from BSON looks this way:
val foo = grater[Foo].asObject(bson)
Here, the role of type parameter is clear. What I was trying to do then is to use the same Grater to serialize any entity from my domain model. So I wrote:
val json = grater[???].toCompactJSON(obj)
I immediately rushed for reflection and just didn't see an obvious solution lying on the surface. Which is:
grater[Entity].toCompactJSON(obj) // where Entity...
#Salat trait Entity // is a root of the domain model hierarchy
Sometimes things are much easier than we think they are! :)
It appears that while I was writing this answer the author of the question realized that he does not need to resolve Manifests at runtime. However, in my opinion it is perfectly legal problem which I resolved successfully when I was writing Yaml [de]serialization library, so I'm leaving the answer here.
It is possible to do what you want using ClassTags or even TypeTags. I don't know about Manifests because that API is deprecated and I haven't worked with it, but I believe that with manifests it will be easier since they weren't as sophisticated as new Scala reflection. FYI, Manifest's successor is TypeTag.
Suppose you have the following functions:
def useClasstag[T: ClassTag](obj: T) = ...
def useTypetag[T: TypeTag](obj: T) = ...
and you need to call then with obj: AnyRef as an argument while providing either ClassTag or TypeTag for obj.getClass class as the implicit parameter.
ClassTag is the easiest one. You can create ClassTag directly from Class[_] instance:
useClasstag(obj)(ClassTag(obj.getClass))
That's all.
TypeTags are harder. You need to use Scala reflection to obtain one from the object, and then you have to use some internals of Scala reflection.
import scala.reflect.runtime.universe._
import scala.reflect.api
import api.{Universe, TypeCreator}
// Obtain runtime mirror for the class' classloader
val rm = runtimeMirror(obj.getClass.getClassLoader)
// Obtain instance mirror for obj
val im = rm.reflect(obj)
// Get obj's symbol object
val sym = im.symbol
// Get symbol's type signature - that's what you really want!
val tpe = sym.typeSignature
// Now the black magic begins: we create TypeTag manually
// First, make so-called type creator for the type we have just obtained
val tc = new TypeCreator {
def apply[U <: Universe with Singleton](m: api.Mirror[U]) =
if (m eq rm) tpe.asInstanceOf[U # Type]
else throw new IllegalArgumentException(s"Type tag defined in $rm cannot be migrated to other mirrors.")
}
// Next, create a TypeTag using runtime mirror and type creator
val tt = TypeTag[AnyRef](rm, tc)
// Call our method
useTypetag(obj)(tt)
As you can see, this machinery is rather complex. It means that you should use it only if you really need it, and, as others have said, the cases when you really need it are very rare.
This isn't going to work. Think about it this way: You're asking the compiler to create a class Manifest (at compile time!) for a class that isn't known until run time.
However, I have the feeling you're approaching the problem the wrong way. Is AnyRef really the most you know about the type of Foo at compile time? If that's the case, how can you do anything useful with it? (You won't be able to call any methods on it except the few that are defined for AnyRef.)
It's not clear what you are trying to achieve and a little more context could be helpful. Anyway, here's my 2 cents.
Using Manifest will not help you here because the type parameter needs to be known at compile time. What I propose is something along these lines:
def myFunc[T](arg: AnyRef, klass: Class[T]) = {
val obj: T = klass.cast(arg)
//do something with obj... but what?
}
And you could call it like this:
myFunc(obj, Foo.class)
Note that I don't see how you can do something useful inside myFunc. At compile time, you cannot call any method on a object of type T beside the methods available for AnyRef. And if you want to use reflection to manipulate the argument of myFunc, then there is no need to cast it to a specific type.
This is the wrong way to work with a type-safe OO language. If you need to do this, your design is wrong.
myFunc[T <: AnyRef](arg: T)(implicit m: Manifest[T]) = ???
This is, of course, useless, as you have probably discovered. What kind of meaningful function can you call on an object which might be anything? You can't make any direct reference to its properties or methods.
I would want to write something logically similar to:
myFunc[objClass](obj.asInstanceOf[objClass])
Why? This kind of thing is generally only necessary for very specialised cases. Are you writing a framework that will use dependency injection, for example? If you're not doing some highly technical extension of Scala's capabilities, this should not be necessary.
I bet you know something more about the class, since you say you don't know the exact type. One big part of the way class-based OO works is that if you want to do something to a general type of objects (including all its subtypes), you put that behaviour into a method belonging to the class. Let subclasses override it if they need to.
Frankly, the way to do what you are attempting is to invoke the function in a context where you know enough about the type.
I am wondering what type do I put in place of XXX
def registerClass(cl:XXX) = kryo.register(classOf[cl])
EDIT: For why I want to do this.
I have to register many classes using the above code. I wanted to remove the duplication of calling kyro.register several times, hoping to write code like below:
Seq(com.mypackage.class1,com.mypackage.class2,com.mypackage.class3).foreach(registerClass)
Another question, can I pass String instead? and convert it somehow to a class in registerClass?
Seq("com.mypackage.class1","com.mypackage.class2").foreach(registerClass)
EDIT 2:
When I write com.mypackage.class1, it means any class defined in my source. So if I create a class
package com.mypackage.model
class Dummy(val ids:Seq[Int],val name:String)
I would provide com.mypackage.model.Dummy as input
So,
kryo.register(classOf[com.mypackage.model.Dummy])
Kryo is a Java Serialization library. The signature of the register class is
register(Class type)
You could do it like this:
def registerClass(cl:Class[_]) = kryo.register(cl)
And then call it like this:
registerClass(classOf[Int])
The type parameter to classOf needs to be known at compile time. Without knowing more about what you're trying to do, is there any reason you can't use:
def registerClass(cl:XXX) = kryo.register(cl.getClass)
I'd like to add implicit conversions to Java classes generated by a modeling tool. So I want to add them to the companion object of those classes, so that the compiler automatically finds them. But I cannot add them in a separate file, because the companion has to be defined in the same file. Is there anything I can do about this?
Of course, I can define all my implicit conversions in another object and then bring it into scope, but this requires an extra import. Any other solution?
You can define your own companion object of course, which I often do in my own project-specific Predef-like arrangement. For example:
object domain {
type TimeUnit = java.util.concurrent.TimeUnit
object TimeUnit {
def valueOf(s : String) = java.util.concurrent.TimeUnit.valueOf(str)
val Millis = java.util.concurrent.TimeUnit.MILLISECONDS
//etc
}
Then this can be used:
import my.domain._
val tu : TimeUnit = TimeUnit.valueOf("MILLISECONDS")
But your domain.TimeUnit is a module (i.e. scala object)
With the Scala compiler as it stands now there is no way to define companion objects other than by putting them in the same file. The best you can do is a non-companion object with the same package and name and an extra import.
If you can think of a good way to create post-hoc companionship without breaking assumptions about encapsulation please come post on http://groups.google.com/group/scala-debate because it would clearly be a very useful feature.