When you create a case class, the compiler creates a corresponding companion object with a few of the case class goodies: an apply factory method matching the primary constructor, equals, hashCode, and copy.
Somewhat oddly, this generated object extends FunctionN.
scala> case class A(a: Int)
defined class A
scala> A: (Int => A)
res0: (Int) => A = <function1>
This is only the case if:
There is no manually defined companion object
There is exactly one parameter list
There are no type arguments
The case class isn't abstract.
Seems like this was added about two years ago. The latest incarnation is here.
Does anyone use this, or know why it was added? It increases the size of the generated bytecode a little with static forwarder methods, and shows up in the #toString() method of the companion objects:
scala> case class A()
defined class A
scala> A.toString
res12: java.lang.String = <function0>
UPDATE
Manually created objects with a single apply method are not automatically considered as FunctionN:
object HasApply {
def apply(a: Int) = 1
}
val i = HasApply(1)
// fails
// HasApply: (Int => Int)
The reason why case class companion objects implement FunctionN is that before, case classes generated a class and a factory method, not a companion object. When we added extractors to Scala it made more sense to turn the factory method into a full companion object with apply and unapply methods. But then, since the factory method did conform to FunctionN, the companion object needed to conform, too.
[Edit] That said, it would make sense to have companion objects show as their own name, not as "function"
Well, given that target.apply(a1, a2, a3 ... aN) in Scala:
can be sugared by target(a1, a2, a3 ... aN)
is the method which needs to be implemented by FunctionN
it seems natural that a companion object:
object MyClass {
def apply(a1 : A1, ... aN: AN) = new MyClass(a1, ..., aN)
}
is really:
object MyClass extends FunctionN[A1, ... , AN, MyClass]{
def apply(a1 : A1, ... aN: AN) = new MyClass(a1, ..., aN)
}
So the addition seems to be natural to me (I'm not sure why it seems "odd" to you?). As to whether it actually added anything; well, that is for someone smarter than me!
Aside from oxbow_lakes's reply about the naturalness of it, it can often be useful to have constructors available as first-class functions, particularly in conjunction with Scala collections higher-order functions. For (a trivial) example,
scala> case class Foo(i : Int)
defined class Foo
scala> List(1, 2, 3) map Foo
res0: List[Foo] = List(Foo(1), Foo(2), Foo(3))
Welcome to Scala version 2.8.0.RC3 (Java HotSpot(TM) Client VM, Java 1.6.0_20).
scala> case class CC3(i: Int, b: Boolean, s: String)
defined class CC3
scala> CC3
res0: CC3.type = <function3>
scala> CC3.apply(1, true, "boo!")
res1: CC3 = CC3(1,true,boo!)
scala> CC3(1, true, "boo!")
res2: CC3 = CC3(1,true,boo!)
Related
I came from C++ world and new to Scala, and this behavior looks unusual.
class G1[A]( val a : A) {
//val c:A = new A //This gives compile error
def fcn1(b: A): Unit = {
//val aobj = new A // This gives compile error
println(a.getClass.getSimpleName)
println(b.getClass.getSimpleName)
}
}
def fcnWithTP[A](): Unit = {
//val a = new A // This gives compile error
//println(a.getClass.getSimpleName)
}
I am not able to crate a object using the type parameter in a class in a function body or a class body. I am only be able to use it in the function parameter.
What is the reason for this? Is this because of type erasure? At run time, the function does not know what the actual type A is, so it cannot create an object of that type?
What is the general rule for this? Does it that mean the type parameter cannot appear in function body or class definition at all? If they can actually appear, what are the examples?
Yes, you're right that this is because of erasure—you don't know anything about A at runtime that you haven't explicitly asserted about it as a constraint in the method signature.
Type erasure on the JVM is only partial, so you can do some horrible things in Scala like ask for the class of a value:
scala> List(1, 2, 3).getClass
res0: Class[_ <: List[Int]] = class scala.collection.immutable.$colon$colon
Once you get to generics, though, everything is erased, so for example you can't tell the following things apart:
scala> List(1, 2, 3).getClass == List("a", "b", "c").getClass
res1: Boolean = true
(In case it's not clear, I think type erasure is unambiguously a good thing, and that the only problem with type erasure on the JVM is that it's not more complete.)
You can write the following:
import scala.reflect.{ ClassTag, classTag }
class G1[A: ClassTag](val a: A) {
val c: A = classTag[A].runtimeClass.newInstance().asInstanceOf[A]
}
And use it like this:
scala> val stringG1: G1[String] = new G1("foo")
stringG1: G1[String] = G1#33d71170
scala> stringG1.c
res2: String = ""
This is a really bad idea, though, since it will crash at runtime for many, many type parameters:
scala> class Foo(i: Int)
defined class Foo
scala> val fooG1: G1[Foo] = new G1(new Foo(0))
java.lang.InstantiationException: Foo
at java.lang.Class.newInstance(Class.java:427)
... 43 elided
Caused by: java.lang.NoSuchMethodException: Foo.<init>()
at java.lang.Class.getConstructor0(Class.java:3082)
at java.lang.Class.newInstance(Class.java:412)
... 43 more
A better approach is to pass in the constructor:
class G1[A](val a: A)(empty: () => A) {
val c: A = empty()
}
And a much better approach is to use a type class:
trait Empty[A] {
def default: A
}
object Empty {
def instance[A](a: => A): Empty[A] = new Empty[A] {
def default: A = a
}
implicit val stringEmpty: Empty[String] = instance("")
implicit val fooEmpty: Empty[Foo] = instance(new Foo(0))
}
class G1[A: Empty](val a: A) {
val c: A = implicitly[Empty[A]].default
}
And then:
scala> val fooG1: G1[Foo] = new G1(new Foo(10101))
fooG1: G1[Foo] = G1#5a34b5bc
scala> fooG1.c
res0: Foo = Foo#571ccdd0
Here we're referring to A in the definition of G1, but we're only making reference to properties and operations that we've confirmed hold or are available at compile time.
Generics are not the same thing as templates. In C++ Foo<Bar> and Foo<Bat> are two different classes, generated at compile time.
In scala or java, Foo[T] is a single class that has with a type parameter. Consider this:
class Foo(val bar)
class Bar[T] {
val foo = new T // if this was possible ...
}
new Bar[Foo]
In C++, (an equivalent of) this would fail to compile, because there is no accessible constructor of Foo that takes no arguments. The compiler would know that when it tried to instantiate a template for Bar<Foo> class, and fail.
In scala, there is no separate class for Bar[Foo], so, at compilation time, the compiler doesn't know anything about T, other than that it is some type. It has no way of knowing whether calling a constructor (or any other method for that matter) is possible or sensible (you can't instantiate a trait for example, or an abstract class), so new T in that context has to fail: it simply does not make sense.
Roughly speaking, you can use type parameters in places where any type can be used (do declare a return type for example, or a variable), but when you are trying to do something that only works for some types, and not for others, you have to make your type param more specific. For example, this: def foo[T](t: T) = t.intValue does not work, but this: def foo[T <: Number](t: T) = t.intValue does.
Well the compiler does not know how to create an instance of type A. You need to either provide a factory function that returns instance of A, or use Manifest which creates instance of A from reflection.
With factory function:
class G1[A](val a:A)(f: () => A) {
val c:A = f()
}
With Manifest:
class G1[A](val a: A)(implicit m: scala.reflect.Manifest[A]) {
val c: A = m.erasure.newInstance.asInstanceOf[A]
}
When using type parameter, usually you will specify more details on the type A, unless you're implementing some sort of container for A that does not directly interact with A. If you need to interact with A, you need some specification on it. You can say A must be a subclass of B
class G1[A <: B](val a : A)
Now compiler would know A is a subclass of B so you can call all functions defined in B on a:A.
Im trying to get the direct super classes / traits of a ClassSymbol. The method baseClasses() does not work for me as it also includes the super super.. types.
The java.lang.Class.getSuperclass() and java.lang.Class.getInterfaces() would actually be sufficient for my use case, but I can't find a way to go from ClassSymbol to java.lang.Class in macro context!
If you use macro - you can't obtain runtime-object Class for class which does not exist (loaded) in compile-time (so you can't have an access to compiling classess from there). But, you could write your own function:
def getDirectBase(a: ClassSymbol) = {
val base = a.baseClasses.toSet - a //`baseClasses` contains `a` itself
val basebase = base.flatMap {
case x: ClassSymbol => x.baseClasses.toSet - x
}
base -- basebase
}
Results (examples obtained using run-time reflection, but compile-time should be same here):
scala> class A
scala> class B extends A
scala> class C extends B
scala> typeOf[C].typeSymbol.asInstanceOf[ClassSymbol].baseClasses
res37: List[reflect.runtime.universe.Symbol] = List(class C, class B, class A, class Object, class Any)
scala> getDirectBase(typeOf[C].typeSymbol.asInstanceOf[ClassSymbol])
res38: scala.collection.immutable.Set[reflect.runtime.universe.Symbol] = Set(class B)
I have a Scala collection that contains objects of different subtypes.
abstract class Base
class A extends Base
class B extends Base
val a1 = new A()
val a2 = new A()
val b = new B()
val s = List(a1, a2, b)
I'd like to filter out all the A objects or the B objects. I can do this easily if I know the object I want to filter on at compile time.
s.filter(_.isInstanceOf[A]) // Give me all the As
s.filter(_.isInstanceOf[B]) // Give me all the Bs
Can I do it if I only know the object type to filter on at runtime? I want to write a function like this.
def filterType(xs:List[Base], t) = xs.filter(_.isInstanceOf[t])
Where t indicates whether I want objects of type A or B.
Of course I can't actually write it this way because of type erasure. Is there an idiomatic Scala way to work around this using type tags? I've been reading the Scala type tag documentation and relevant StackOverflow posts, but I can't figure it out.
This has come up a few times. Duplicate, anyone?
scala> trait Base
defined trait Base
scala> case class A(i: Int) extends Base
defined class A
scala> case class B(i: Int) extends Base
defined class B
scala> val vs = List(A(1), B(2), A(3))
vs: List[Product with Serializable with Base] = List(A(1), B(2), A(3))
scala> def f[T: reflect.ClassTag](vs: List[Base]) = vs collect { case x: T => x }
f: [T](vs: List[Base])(implicit evidence$1: scala.reflect.ClassTag[T])List[T]
scala> f[A](vs)
res0: List[A] = List(A(1), A(3))
Type erasure will destroy any information in type parameters, but objects still know what class they belong to. Because of this, we cannot filter on arbitrary types, but we can filter by class or interface/trait. ClassTag is preferable to TypeTag here.
import scala.reflect.ClassTag
def filterType[T: ClassTag](xs: List[Base]) = xs.collect {
case x: T => x
}
Which we can use like:
scala> filterType[B](s)
res29: List[B] = List(B#42096939)
scala> filterType[Base](s)
res30: List[Base] = List(A#8dbc09c, A#625f8cc7, B#42096939)
This method is safe at run-time if type T is not generic. If there was a class C[T] extends Base we could not safely filter on C[String].
I'm building a MultiSet[A] and using a TreeMap[A, Int] to keep track of the elements.
class MultiSet[A <: Ordered[A] ](val tm: TreeMap[A, Int]) { ... }
Now I want to create a MultiSet[Int] using this framework. In particular, I want a method that will take a Vector[Int] and produce a TreeMap[Int, Int] that I can use to make a MultiSet[Int].
I wrote the following vectorToTreeMap, which compiles without complaint.
def vectorToTreeMap[A <: Ordered[A]](elements: Vector[A]): TreeMap[A, Int] =
elements.foldLeft(new TreeMap[A, Int]())((tm, e) => tm.updated(e, tm.getOrElse(e, 0) + 1))
But when I try
val tm: TreeMap[Int, Int] = vectorToTreeMap(Vector(1, 2, 3))
I get compiler complaints saying that Int doesn't conform to A <: Ordered[A]. What does it take to create a TreeMap[Int, Int] in this context? (I want the more general case because the MultiSet[A] is not always MultiSet[Int].)
I also tried A <: scala.math.Ordered[A] and A <: Ordering[A] but with no better results. (I'll admit that I don't understand the differences among the three possibilities and whether it matters in this situation.)
Thanks for your help.
The problem is that Int is an alias for the java int, which does not implement Ordered[Int]. How could it, since java does not even know that the Ordered[T] trait exists.
There are two ways to solve your problem:
View bounds:
The first approach is to change the constraint <: to a view bound <%.
def vectorToTreeMap[A <% Ordered[A]](elements: Vector[A]): TreeMap[A, Int] =
elements.foldLeft(new TreeMap[A, Int]())((tm, e) => tm.updated(e, tm.getOrElse(e, 0) + 1))
A <: Ordered[A] means that the method vectorToTreeMap is only defined for types that directly implement Ordered[A], which excludes Int.
A <% Ordered[A] means that the method vectorToTreeMap is defined for all types that "can be viewed as" implementing Ordered[A], which includes Int because there is an implicit conversion defined from Int to Ordered[Int]:
scala> implicitly[Int => Ordered[Int]]
res7: Int => Ordered[Int] = <function1>
Type classes
The second approach is to not require any (direct or indirect) inheritance relationship for the type A, but just require that there exists a way to order instances of type A.
Basically you always require an ordering to be able to create a TreeMap from a vector, but to avoid having to pass it every single time you call the method you make the ordering an implicit parameter.
def vectorToTreeMap[A](elements: Vector[A])(implicit ordering:Ordering[A]): TreeMap[A, Int] =
elements.foldLeft(new TreeMap[A, Int]())((tm, e) => tm.updated(e, tm.getOrElse(e, 0) + 1))
It turns out that there are instances of Ordering[A] for all java primitive types as well as for String, as you can see with the implicitly method in the scala REPL:
scala> implicitly[Ordering[Int]]
res8: Ordering[Int] = scala.math.Ordering$Int$#5b748182
Scala is even able to derive orderings for composite types. For example if you have a Tuple where there exists an ordering for each element type, scala will automatically provide an ordering for the tuple type as well:
scala> implicitly[Ordering[(Int, Int)]]
res9: Ordering[(Int, Int)] = scala.math.Ordering$$anon$11#66d51003
The second approach of using so-called type classes is much more flexible. For example, if you want a tree of plain old ints, but with reverse order, all you have to do is to provide a reverse int ordering either directly or as an implicit val.
This approach is also very common in idiomatic scala. So there is even special syntax for it:
def vectorToTreeMap[A : Ordering](elements: Vector[A]): TreeMap[A, Int] = ???
is equivalent to
def vectorToTreeMap[A](elements: Vector[A])(implicit ordering:Ordering[A]): TreeMap[A, Int] = ???
It basically means that you want the method vectorToTreeMap defined only for types for which an ordering exists, but you do not care about giving the ordering a name. Even with the short syntax you can use vectorToTreeMap with an implicitly resolved Ordering[A], or pass an Ordering[A] explicitly.
The second approach has two big advantages:
it allows you to define functionality for types you do not "own".
it allows you to decouple the behavior regarding some aspect like e.g. ordering from the type itself, whereas with the inheritance approach you couple the behavior to the type. For example you can have a normal Ordering and a caseInsensitiveOrdering for a Sting. But if you let String extend from Ordered, you must decide on one ordering behavior.
That is why the second approach is used in the scala collections itself to provide an ordering for TreeMap.
Edit: here is an example to provide an ordering for a type that does not have one:
scala> case class Person(name:String, surname:String)
defined class Person
scala> implicitly[Ordering[Person]]
<console>:10: error: No implicit Ordering defined for Person.
implicitly[Ordering[Person]]
^
Case classes do not have orderings automatically defined. But we can easily define one:
scala> :paste
// Entering paste mode (ctrl-D to finish)
case class Person(name:String, surname:String)
object Person {
// just convert to a tuple, which is ordered by the individual elements
val nameSurnameOrdering : Ordering[Person] = Ordering.by(p => (p.name, p.surname))
// make the nameSurnameOrdering the default that is in scope unless something else is specified
implicit def defaultOrdering = nameSurnameOrdering
}
// Exiting paste mode, now interpreting.
defined class Person
defined module Person
scala> implicitly[Ordering[Person]]
res1: Ordering[Person] = scala.math.Ordering$$anon$9#50148190
I have two case classes
case class StringCaseClass(argument: String)
case class IntCaseClass(argument: Int)
I want to define a structural type which will match the companion object of both of these
type HasApply1 {
def apply[A, R](argument: A): R
}
This will compile fine, but when I try to use it like this
def method(caseClass: HasApply1) {
// whatever
}
method(StringCaseClass)
I will get a compiler error
found : StringCaseClass.type
required: WithApply1
(which expands to) AnyRef{def apply[A, R](string: A): R}
Is there any way of accomplishing this? If I redefine the structural type to have concrete types for A and R it will compile correctly, but then I lose the flexiblity
#aloiscochard's comment is almost there. What he forgot to mention is that case class companion objects already implement the appropriate FunctionN trait, so you can simply do this,
scala> case class StringCaseClass(argument: String)
defined class StringCaseClass
scala> case class IntCaseClass(argument: Int)
defined class IntCaseClass
scala> def method[A, R](caseClass: A => R, a: A) = caseClass(a)
method: [A, R](caseClass: A => R, a: A)R
scala> method(StringCaseClass, "foo")
res0: StringCaseClass = StringCaseClass(foo)
scala> method(IntCaseClass, 23)
res1: IntCaseClass = IntCaseClass(23)
In general you should avoid structural typing as it's very expensive. The call will be converted into a reflection call because of limitations in the JVM. When you start using scala 2.10 structural types will result in a warning at compile time (though you could disable that using a flag).
If you're looking into a more general way to add functionality to classes that don't share an inheritance hierarchy you could use Type Classes.
Here's a quick example:
trait CanCreateRFromA[A,R]{
def createNew(a:A): R
}
implicit object CanCreateBlahFromInt extends CanCreateRFromA[Int,Blah2]{
def createNew(i:Int):Blah2 = new Blah2(i)
}
implicit object CanCreateBlah1FromString extends CanCreateRFromA[String,Blah1]{
def createNew(s:String):Blah1 = new Blah1(s)
}
case class Blah1(something:String)
case class Blah2(something:Int)
def createRFromA[A,R](a:A)(implicit tc:CanCreateRFromA[A,R])= tc.createNew(a)
Then you can call:
createRFromA(1) // This gives a Blah2
createRFromA("1") // This gives a Blah1
Again I'm not sure what you're trying to accomplish, but it probably is possible to do what you want with a type class and it will be much faster.
You didn't pass an instance of StringCaseClass to your method. What you passed there is companion object of StringCaseClass (which is automatically generated for case classes).
Try if this works: method(StringCaseClass("dummy")).