scala - 有效地将 AnyVal 案例类 (Seq[T <: AnyVal]) 的序列转换为其运行时表示
问题描述
假设我有一个价值案例类
case class Id(i:Int) extends AnyVal
以及包含此值案例类的序列
Seq(Id(1), Id(2), Id(3))
有没有一种方法可以将这些值转换为Int
不需要对序列进行迭代的方法(例如,通过Seq(Id(1), Id(2), Id(3)).map(_.i)
?
我问的原因是我认为值案例类的好处是您可以在运行时使用具有本机类型的值类作为表示,因此非常有效。但并非所有正在使用的库都支持这些类的自动“转换”。因此,当它是一个简单的属性时,必须传递本机类型,这没什么大不了的,因为编译器可以对其进行优化。但是当有一个序列时,我必须显式地映射它,这意味着对所有值都会发生不必要的迭代,因为它实际上除了在运行时映射到相同的值之外什么都不做。有没有办法避免这种情况并在这种情况下使用编译器的一些优化?
解决方案
正如 Alexey Romanov 在评论中推测的那样,值类在存储在Seq
. 这是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
请注意,返回类型是Seq<Id>
并且Id."<init>"
在第 17 行被调用。鉴于此,没有映射的拆箱是不可能的。
如果该提议被接受,则此拳击的解决方案将是Scala 3 中的不透明类型。不过,我不确定他们是否会解决您的问题。
推荐阅读
- redirect - http 不会在 Google Chrome 上转发到 https
- javascript - 使用 node.js 单击时使用 javascript 插入数据库
- python - 使用 PRAW,“print submit.add_comment(response)”收到语法错误
- python - 使用 Python PyInquirer 和 asyncio 创建用户界面以触发异步操作
- python - 将 Flask 应用程序上传到 AWS 上的 Elastic Beanstalk 时,为什么会出现此错误?
- css - 随机平铺背景
- python - python3 ctypes的无效句柄错误 - 昨天工作
- c++ - std::unordered_multiset 的不同元素的数量
- python - 从下拉列表中选择一个值
- java - 使用 JAXB 在 JAVA 中将 CSV 文件转换为层次结构 XML