Invoke a method with a named parameter through reflection - scala

Say I define the following case class:
case class A(x: Int, y: String, s: Double)
and I want to be able dynamically call the copy method via reflection to achieve something like the following:
val a1 = A(1, "hello", 2.3)
val a2 = a1.copy(y = "goodbye") // Do this with reflection???
Is it possible to do the copy via reflection?
Thanks
Des

At the moment Scala's runtime reflection library doesn't provide a convenient way to invoke methods with named/default arguments. Current API only allows reflective calls to methods when the user explicitly provides arguments for all parameters in their declaration order. Please submit an issue to our bug tracker, and I'll be happy to look into it.

Related

Calling type-specific code from a library function, determined at compile-time

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.

Where does type class inherit `.apply` in scala?

I am looking at this code
def loginForm = Form(mapping("username" -> text, "password" -> text)
(LoginRequest.apply)(LoginRequest.unapply))
case class LoginRequest(username:String, password:String)
Here is the source code for Form in Play
def mapping[R, A1, A2](a1: (String, Mapping[A1]),
a2: (String, Mapping[A2]))
(apply: Function2[A1, A2, R])
(unapply: Function1[R, Option[(A1, A2)]]):
Mapping[R] = {
new ObjectMapping2(apply, unapply, a1, a2)
}
I am trying to figure out what
LoginRequest.apply
actually means and what
ObjectMapping2(LoginRequest.apply, LoginRequest.unapply, "username" -> text, "password" -> text)
do
Your LoginRequest is a case class and as such contains methods apply and unapply, inserted automatically by the compiler. Play need them to know how to construct and deconstruct your domain object from the mapping. If you had some custom code you would need a custom apply/unapply, but since you're using a case class (which is the correct practice) you can simply pass its apply and unapply functions which you get out of the box.
So, to answer your first question, LoginRequest.apply is an invocation of apply function available for every case class.
To answer your second question,
ObjectMapping2(LoginRequest.apply, LoginRequest.unapply, "username" -> text, "password" -> text)`
is saying that a new LoginRequest will be created from "username" and "password" strings by passing them to LoginRequest.apply which is a constructor for your LoginRequest case class. It also says that deconstructing of your LoginRequest is done using LoginRequest.unapply, which will return Option[(String, String)] (one string for each parameter, in your case username and password).
EDIT:
I've been rightfully warned in the comments to be more precise. So, when defining a case class, compiler will automatically generate apply() and unapply() in its companion object. You can always include these methods, in any companion object of any class you define. In this situation compiler does it for you. Method apply() is "special" in the sense that it allows a special syntax sugar: instead of invoking Something.apply(), it can also be invoked as simply Something().
Note that apply() and unapply() are not overridden or implemented; you (or in this case the compiler) are simply defining them from scratch just like any other custom method. But it's the "trick" in the Scala compiler that allows the syntax sugar. So, if you define a method apply() in MyClass's companion object, you are of course allowed to call it in the usual way as MyClass.apply(whatever), but also as MyClass(whatever) (that's the trick part).
You use this all the time even if you're sometimes not aware of it - for example, List(1, 2, 3) is actually desugared by the compiler into List.apply(1, 2, 3). This trick allows us programmers to write prettier and more readable code (List.apply() is ugly, isn't it?)
Unrelated to this particular question, but let me mention that too - compiler will also add some other methods for case classes: copy, toString, equals and hashCode. Unlike apply and unapply, these methods will be added to the class (so instead of invoking on companion object like apply and unapply, those need to be invoked upon an instance of the case class).

Can scala accept any derivation of a tuple as an argument list?

Is scala really designed and implemented so that there is no way to transform a tuple into something acceptable as an argument list? In How to pass a tuple argument the best way? it goes the other way around - transforming the argument accepting method. This does not seem to cover a trivial use case:
At the lack of such a way, code becomes clumsy for example when you try to extend a class that takes parameters, e.g. when you wish to extend an arguments-taking-class you can't modify the source code of. In such case you need to spawn out a factory object for overcoming the above limitation, as no function can be substituted for the argument list of the class being extended. So you work around it by creating a factory object that instantiates the class you wish to extend rather than just extending it, as a workaround. This kind of workaround is conspicuous and non-economical to me.
Thanks in advance.
This can be achieved using standard language features.
You can define an extending class that only translates from a tuple to the arguments expected by the original class definition.
Example
class TakeTwo(a: Int, b: Int)
class TakeTwoTuple( t : (Int,Int) ) extends TakeTwo(t._1, t._2)
scala> val tuple = (3,4)
tuple: (Int, Int) = (3,4)
scala> new TakeTwoTuple(tuple)

Scala case class.type does not take parameters

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()

Scala: How to invoke method with type parameter and manifest without knowing the type at compile time?

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.