如何在 Scala 运行时检查我在 @specialized 函数或 class 中?
How to check I'm inside a @specialized function or class at runtime in scala?
假设我有一个专门的 class 和一个关联的伴随对象:
trait Slice[@specialized +T] {
...
override def equals(that :Any) = that match {
case s :Slice[_] => ???
case _ => false
}
}
object Slice {
def newInstance[@specialized T] = ???
}
有什么方法可以查
- 如果此实例是专门的子实例,则在 Slice 的方法中class,
- 在 Slice 的方法内,如果另一个实例是同一原语的专用子class,
- 如果我是 运行 已删除或专门的变体,则在伴随对象的专门方法中
不诉诸 Class 标签或手动传递 Class[_]?似乎该信息应该可用,但我能想到的唯一方法是检查 classes.
的名称
用例 2) 特别重要,因为如果我知道我正在比较苹果与苹果,我可以求助于更快的算法。它可能 可以 通过反射来完成,但是当你考虑到我们还必须处理 Slice 的非合成子 class 时,这将是非常棘手的;如果我们还有
trait ArraySlice[@specialized T] extends Slice[T] { ... }
应该考虑 'compatible' 与 Slice[T] 实例,只要它们都是专用的(或都被擦除)?
好的,我想出了一个更简洁的方法:
final val AllButUnit = new Specializable.Group((Byte, Short, Int, Long, Char, Float, Double, Boolean, AnyRef))
def specializationFor[@specialized(AllButUnit) E] :ResolvedSpecialization[E] =
Specializations(new SpecializedKey[E]).asInstanceOf[ResolvedSpecialization[E]]
private val Specializations = Seq(
resolve[Byte],
resolve[Short],
resolve[Int],
resolve[Long],
resolve[Char],
resolve[Float],
resolve[Double],
resolve[Boolean],
resolve[Unit],
resolve[AnyRef]
).map(
spec => spec.key -> spec :(SpecializedKey[_], ResolvedSpecialization[_])
).toMap.withDefaultValue(resolve[AnyRef])
private def resolve[@specialized(AllButUnit) E :ClassTag] :ResolvedSpecialization[E] =
new ResolvedSpecialization[E](new SpecializedKey[E], new Array[E](0))
class ResolvedSpecialization[@specialized(AllButUnit) E] private[SpecializedCompanion]
(val array :Array[E], val elementType :Class[E], val classTag :ClassTag[E], private[SpecializedCompanion] val key :SpecializedKey[E])
{
private[SpecializedCompanion] def this(key :SpecializedKey[E], array :Array[E]) =
this(array, array.getClass.getComponentType.asInstanceOf[Class[E]], ClassTag(array.getClass.getComponentType.asInstanceOf[Class[E]]), key)
override def toString = s"@specialized($elementType)"
override def equals(that :Any) = that match {
case r :ResolvedSpecialization[_] => r.elementType==elementType
case _ => false
}
override def hashCode = elementType.hashCode
}
private class SpecializedKey[@specialized(AllButUnit) E] {
override def equals(that :Any) = that.getClass==getClass
override def hashCode = getClass.hashCode
def className = getClass.getName
override def toString = className.substring(className.indexOf("$")+1)
}
现在specializationFor[E].elementType
returnsclass对应E的特化参数
假设我有一个专门的 class 和一个关联的伴随对象:
trait Slice[@specialized +T] {
...
override def equals(that :Any) = that match {
case s :Slice[_] => ???
case _ => false
}
}
object Slice {
def newInstance[@specialized T] = ???
}
有什么方法可以查
- 如果此实例是专门的子实例,则在 Slice 的方法中class,
- 在 Slice 的方法内,如果另一个实例是同一原语的专用子class,
- 如果我是 运行 已删除或专门的变体,则在伴随对象的专门方法中
不诉诸 Class 标签或手动传递 Class[_]?似乎该信息应该可用,但我能想到的唯一方法是检查 classes.
的名称用例 2) 特别重要,因为如果我知道我正在比较苹果与苹果,我可以求助于更快的算法。它可能 可以 通过反射来完成,但是当你考虑到我们还必须处理 Slice 的非合成子 class 时,这将是非常棘手的;如果我们还有
trait ArraySlice[@specialized T] extends Slice[T] { ... }
应该考虑 'compatible' 与 Slice[T] 实例,只要它们都是专用的(或都被擦除)?
好的,我想出了一个更简洁的方法:
final val AllButUnit = new Specializable.Group((Byte, Short, Int, Long, Char, Float, Double, Boolean, AnyRef))
def specializationFor[@specialized(AllButUnit) E] :ResolvedSpecialization[E] =
Specializations(new SpecializedKey[E]).asInstanceOf[ResolvedSpecialization[E]]
private val Specializations = Seq(
resolve[Byte],
resolve[Short],
resolve[Int],
resolve[Long],
resolve[Char],
resolve[Float],
resolve[Double],
resolve[Boolean],
resolve[Unit],
resolve[AnyRef]
).map(
spec => spec.key -> spec :(SpecializedKey[_], ResolvedSpecialization[_])
).toMap.withDefaultValue(resolve[AnyRef])
private def resolve[@specialized(AllButUnit) E :ClassTag] :ResolvedSpecialization[E] =
new ResolvedSpecialization[E](new SpecializedKey[E], new Array[E](0))
class ResolvedSpecialization[@specialized(AllButUnit) E] private[SpecializedCompanion]
(val array :Array[E], val elementType :Class[E], val classTag :ClassTag[E], private[SpecializedCompanion] val key :SpecializedKey[E])
{
private[SpecializedCompanion] def this(key :SpecializedKey[E], array :Array[E]) =
this(array, array.getClass.getComponentType.asInstanceOf[Class[E]], ClassTag(array.getClass.getComponentType.asInstanceOf[Class[E]]), key)
override def toString = s"@specialized($elementType)"
override def equals(that :Any) = that match {
case r :ResolvedSpecialization[_] => r.elementType==elementType
case _ => false
}
override def hashCode = elementType.hashCode
}
private class SpecializedKey[@specialized(AllButUnit) E] {
override def equals(that :Any) = that.getClass==getClass
override def hashCode = getClass.hashCode
def className = getClass.getName
override def toString = className.substring(className.indexOf("$")+1)
}
现在specializationFor[E].elementType
returnsclass对应E的特化参数