Reputation: 411
Assuming I have a value case class
case class Id(i:Int) extends AnyVal
and a sequence containing this value case class
Seq(Id(1), Id(2), Id(3))
is there a way of converting those values into Int
without that there is a need of iteration over the sequence (e.g. by doing Seq(Id(1), Id(2), Id(3)).map(_.i)
?
The reason I ask is that I think that the nice thing about value case classes is that you can use value classes that have native types as representation during runtime and are thus extremely efficient. But not all libraries in use do support an automatic "conversions" of those classes. Thus one has to pass the native type what is no big deal when it is a simple attribute since the compiler can optimize it. But when having a sequence I have to explicitly map it, which means that there happens an unnecessary iteration over all values, because it is actually doing nothing but mapping to the same values at runtime. Is there any way to avoid that and use some optimizations of the compiler in such cases?
Upvotes: 7
Views: 153
Reputation: 8584
As conjectured by Alexey Romanov in the comments, value classes actually box when stored in a Seq
. Here's the output of javap -c
for def bar = Seq(Id(1))
:
public scala.collection.Seq<Id> bar();
Code:
0: getstatic #25 // Field scala/collection/Seq$.MODULE$:Lscala/collection/Seq$;
3: getstatic #30 // Field scala/Predef$.MODULE$:Lscala/Predef$;
6: iconst_1
7: anewarray #32 // class Id
10: dup
11: iconst_0
12: new #32 // class Id
15: dup
16: iconst_1
17: invokespecial #35 // Method Id."<init>":(I)V
20: aastore
21: invokevirtual #39 // Method scala/Predef$.genericWrapArray:(Ljava/lang/Object;)Lscala/collection/mutable/WrappedArray;
24: invokevirtual #43 // Method scala/collection/Seq$.apply:(Lscala/collection/Seq;)Lscala/collection/GenTraversable;
27: checkcast #45 // class scala/collection/Seq
30: areturn
Notice that the return type is Seq<Id>
and that Id."<init>"
is called at line 17. Given this, unboxing without mapping is impossible.
The solution to this boxing will be Opaque Types in Scala 3, if that proposal is accepted. I'm not sure if they will solve your problem, though.
Upvotes: 2