How to understand a Scala's method declaration? - scala

I'm new to Scala and got into troubles with understanding this declaration:
Here's the declaration from Akka's Props object:
def apply[T <: Actor: ClassTag](): Props = __THE_DEFENITION_GOES_HERE__
Why can we use it like this:
val props = Props[TestActor]
where class TestActor extends Actor. I'm curious about how just by Generic Type argument, the compiler is able to find the appropriate method defenition. How does it work?

There is some special magic involved with the apply method in a Scala object. This:
val something = Hello()
is special shortcut syntax for this:
val something = Hello.apply()
Similarly, looking at your example:
val props = Props[TestActor]
is just short syntax for this:
val props = Props.apply[TestActor]()
The [TestActor] is just filling in the type argument for the apply method.

Related

Scala/Akka Syntax

I'm new to both Scala and Akka and have been following this tutorial. I came across the following and wondering what exactly this syntax does/mean?
import akka.actor.Props
val props1 = Props[MyActor] //Not sure what this means???
val props2 = Props(new ActorWithArgs("arg")) // careful, see below
val props3 = Props(classOf[ActorWithArgs], "arg")
I'm not sure what the line commented with //Not sure what this means does? It seems like a generic trait that gives a parameterised type. If I look at the source code, akka.actor.Props is defined as an Object that extends the trait AbstractProps. However, AbstractProps is not defined with a type parameter i.e. AbstractProps[T]. Can someone explain how that above line works and what it does?
In Scala, any object which implements an apply method can be called without the new keyword, simply by calling MyObject(), which will automatically lookup for it's apply.
If you look at the companion object for Props, you'll see the following method defined:
/**
* Scala API: Returns a Props that has default values except for "creator"
* which will be a function that creates an instance
* of the supplied type using the default constructor.
*/
def apply[T <: Actor: ClassTag](): Props =
apply(defaultDeploy, implicitly[ClassTag[T]].runtimeClass, List.empty)
This apply takes one type parameter and no arguments. T <: Actor means that T, the type you're passing, must extend Actor. That's how Scala knows how to create the object.
Additionally, any method with arity-0 in Scala may drop it's parenthesis. That's how you're seeing Props[MyActor] actually compile, as it is equivalent of Props[MyActor](), which is equivalent to Props.apply[MyActor]().
akka.actor.Props is defined as an Object that extends the trait
AbstractProps
Its also defined as a case class:
final case class Props(deploy: Deploy, clazz: Class[_], args: immutable.Seq[Any])
This is a common pattern in Scala, a class with a companion object. The companion object frequently houses factory methods, and thats what your actually calling in your example.
val props1 = Props[MyActor]
This simply calls apply() of the companion object. You can omit the parentheses in Scala if no arguments are neccessary and apply is a special method that can be invoked directly on the object/instance. Say you have a sequence and want the element at index 1:
val s = Seq("one", "two", "three")
// These two are equivalent
s(1) // -> "two"
s.apply(1) // -> "two"
Ultimately your code can be rewritten as
val props1 = Props.apply[MyActor]()

What feature of Scala allows for Props[SomeActor] syntax

One aspect of Akka I've always just glossed over appears right in the canonical Hello World! example. That is, the syntax for creating a Props class:
val props = Props[MyActor]
Q. What mechanism in Scala is allowing for the type parameter (i.e. [MyActor]) to be specified in this way? I'm assuming this gets translated to a constructor/apply method on Props that takes a Class parameter? For instance, my guess is it's equivalent to:
val props = Props(classOf[MyActor])
I've always assumed classOf was "special" and somehow cheated in order to use the [] syntax. Since I see that Akka, a 3rd party library, utilizes the same syntax it would be great to see a simple REPL example that demonstrates how I can utilize this syntax for my own classes.
Instances of Props are ultimately of the following case class (https://github.com/akka/akka/blob/0511b07f3e50e0422379075ae76dd158e4d377fa/akka-actor/src/main/scala/akka/actor/Props.scala#L115):
final case class Props(deploy: Deploy, clazz: Class[_], args: immutable.Seq[Any])
Since this is a case class, scala will generate default apply method of
Props.apply(deploy: Deploy, clazz: Class[_], args: immutable.Seq[Any])
The Props companion object has several other apply methods which create instances of this class for you, using the default apply method. In the case of Props[MyActor], this is the method:
def apply[T <: Actor: ClassTag](): Props = apply(defaultDeploy, implicitly[ClassTag[T]].runtimeClass, List.empty)
Props[MyActor] is syntactic sugar for Props.apply[MyActor](). So Props is using the reflection capabilities of ClassTag in order to get the runtime class of MyActor, so it can satisfy the parameter clazz: Class[_] of the Props case class.
It is the Scala ClassTag mechanism. For instance:
object Test {
def apply[T: ClassTag](s: String): Option[T] = ...
}
val foo = Test[Foo]("foo")
In the apply method you can simply do something like
val ctor = implicitly[ClassTag[T]].runtimeClass.getConstructors.head
in order to get access to the first constructor of T for example.

Get a class from a type scala

In scala, I want to be able to say
val user = Node.create[User](...) // return User object
So here's what I have so far:
def create[T : TypeTag](map: Map[String, Any]) {
val type = typeOf[T]
// create class from type here???
}
I've been digging around how to create classes from generic types and found out that using ClassManifest seems to be deprecated. Instead, type tags are here, so I'm able to do something like this typeOf[T] and actually get the type.. but then I'm lost. If I could get the class, then I could use something like class.newInstance and manually set the fields from there.
Question is: given a type, can I get a class instance of the given type?
The easiest way in fact is to use ClassTag:
def create[T : ClassTag](map: Map[String, Any]): T = {
val clazz: Class[_] = classTag[T].runtimeClass
clazz.newInstance(<constructor arguments here>).asInstanceOf[T]
}
ClassTag is a thin wrapper around Java Class, primarily used for arrays instantiation.
TypeTag facility is more powerful. First, you can use it to invoke Java reflection:
import scala.reflect.runtime.universe._
def create[T: TypeTag](map: Map[String, Any]): T = {
val mirror = runtimeMirror(getClass.getClassLoader) // current class classloader
val clazz: Class[_] = mirror.runtimeClass(typeOf[T].typeSymbol.asClass)
clazz.newInstance(<constructor arguments here>).asInstanceOf[T]
}
However, Scala reflection allows to instantiate classes without dropping back to Java reflection:
def create[T: TypeTag](map: Map[String, Any]): T = {
// obtain type symbol for the class, it is like Class but for Scala types
val typeSym = typeOf[T].typeSymbol.asClass
// obtain class mirror using runtime mirror for the given classloader
val mirror = runtimeMirror(getClass.getClassLoader) // current class classloader
val cm = mirror.reflectClass(typeSym)
// resolve class constructor using class mirror and
// a constructor declaration on the type symbol
val ctor = typeSym.decl(termNames.CONSTRUCTOR).asMethod
val ctorm = cm.reflectConstructor(cm)
// invoke the constructor
ctorm(<constructor arguments here>).asInstanceOf[T]
}
If you want to create a class with overloaded constructors, it may require more work though - you'll have to select correct constructor from declarations list, but the basic idea is the same. You can read more on Scala reflection here
There is a way to do it with reflection: either runtime reflection, or in a macro. Regarding runtime reflection way, you can have a look at my blog post where I tried to do something like what you are trying to do now. Using compile-time reflection with macros might be a better option, depending on your need.

Akka actor construction in Play! framework

I am playing with the Play! framework and I wanted to create a factory called Services which will create new actors. I have this so far
class UserRegistration extends Actor {
def receive = {
case "foo" => "bar"
}
}
object UserRegistration {
val path: String = "user/registration"
}
object Services {
val system = ActorSystem("Services")
def apply[A<:Actor]: ActorRef = system.actorOf(Props[A], A.path)
}
And I wanted to create and pass messages to actors like this:
Services[UserRegistration] ? "hello"
but I get errors of the type could not find implicit value for evidence parameter of type ClassManifest[A]. Can anyone please tell me what am I doing wrong here? And if this is a valid construction in general (a best practice). I am pretty new in Scala and still learning stuff.
Thanks!
senia's answer works too, but if you want to specify a common path for each type of actor, you need a second implicit parameter(the first being the ClassManifest so that you can specify a path for each type of actor. Keep in mind that actor names have to be unique though, so you have to add something to that path.
First you define a class that holds the Path:
case class Path(value:String)
Then you define an implicit value in the companion object of your actor class:
object SomeActor {
implicit val path = Path("SomeActor")
}
Finally you modify the apply method to take an implicit class manifest as well as an implicit path.
def apply[A<:Actor](implicit cm:ClassManifest[A], path:Path[A]): ActorRef =
system.actorOf(Props[A], path.value + someIndex)
Method apply of object Props implicitly takes parameter of type ClassManifest[T].
apply [T <: Actor] (implicit arg0: ClassManifest[T])
You have to add such parameter into your method:
def apply[A<:Actor : ClassManifest]: ActorRef = system.actorOf(Props[A])

Scala mixin to class instance

Is it possible in Scala to make some mixin to class instance?
Eg: I have some MyClass instance var x = new MyClass and I want to extend it on some method or trait without copying it.
[Edit:]
I'm looking the way to extend x after it has been instantiated.
So, for example in a function method, which gets x as a parameter.
[What is behind]
I've just wonder if there is some magic with implicit objects and Manifest to achieve the typeclass pattern without explicit call implicit object (like in Haskell).
But only for single object.
I know if is artificial, but I've just wonder if it's possible because of lot of magic with mixing Scalas features.
you mean like:
val x = new MyClass with MyTrait
Yes you can. Just overriding methods obviously can be:
val x = new MyClass {
override def myMethod = { my implementation }
}
Just came across this problem as I was wondering the same thing...
case class Person(name: String)
val dave = Person("Dave")
val joe = Person("Joe")
trait Dog { val dogName: String }
val spot = new Dog { val dogName = "Spot" }
implicit def daveHasDog(p: dave.type) = spot
dave.dogName //"Spot"
joe.dogName //error: value dogName is not a member of Person
So now the dave instance (rather than all instances of class Person) behaves like a Person with Dog, at long as the implicit is in scope.
This will work in most cases, except where your trait has self-types.
It is not possible. You may look at using the Dynamic trait or Kevin Wright's auto-proxy plugin, but, either way, you'll create a new object that also answers to the original one's method through proxying.