我想在我的Scala代码中使用基本类型安全的“子类”,而不会出现拳击的性能损失(对于非常低延迟的应用程序)。例如,像这样:
class Timestamp extends Long
class ProductId extends Long
def process(timestamp: Timestamp, productId: ProductId) {
...
}
val timestamp = 1: Timestamp // should not box
val productId = 1: ProductId // should not box
process(timestamp, productId) // should compile
process(productId, timestamp) // should NOT compile
有一个thread on the Scala User mailing list last year似乎认为没有拳击是不可能的,但我想知道现在是否可以在Scala 2.8中使用。
答案 0 :(得分:3)
为什么不使用类型别名呢?我感谢他们并不完美(即他们没有解决你的编译问题),但他们可以让你的代码更清晰,而不会影响性能?
type Timestamp = Long
type ProductId = Long
然后你可以编写使用 pimp my library 模式的方法,并让JVM使用转义分析来消除运行时开销:
class RichTimestamp(self: Timestamp) {
//whatever you want here
}
请注意,所有常见的警告都适用:除非您非常确定(因为您正在进行超低延迟编程),否则使用盒装类型的性能可能不是问题。我处理的系统每天处理数以千万计的输入,没有任何问题!
答案 1 :(得分:2)
Scala类型层次结构的根目录是Any
,其中包含子级AnyVal
和Anyref
。所有整数类型(例如示例中的Long
)都来自AnyVal
,您无法在树的那一侧创建子类。 AnyVal
的子项代表JVM中的低级类型。类型擦除意味着在运行时不再有AnyVal
,如果你可以使Timestamp
它也会在运行时丢失。您需要装箱/拆箱作为存储包装类型信息的地方。
case class Timestamp(ts: Long)
一个好的JVM可以在运行时消除大量的装箱/拆箱开销。例如,请参阅Experiences with escape analysis enabled on the JVM
答案 2 :(得分:1)
原语(on the JVM)的概念是它们是预定义的和最终的,你不能将其他原语添加到JVM中,只能添加类(Java中的java.lang.Object或Scala中的scala.AnyRef)。
Ben,case class Timestamp(ts: Long)
提出的封装器的装箱/拆箱不应该造成严重的性能问题。
类型别名type Timestamp = Long
实际上是别名,因此编译器无法将两个别名区分为相同的类型(Long
)。
答案 3 :(得分:1)
插件可以确保这种事情。毕竟,Scala不受支持和不工作的单元插件在阻止将距离添加到持续时间时做了类似的事情。
答案 4 :(得分:0)
从2.10版开始,pytorch docs现在现在。