How can one provide manually specialized implementations with Scala specialization?

后端 未结 3 797
渐次进展
渐次进展 2020-12-28 14:40

Specialization promises to provide high-efficiency implmentations for primitive types with minimal extra boilerplate. But specialization seems to be too eager for its own g

3条回答
  •  离开以前
    2020-12-28 15:23

    I know it's quite old, but I bumped at it looking for something else and maybe it'll prove useful. I had a similar motivation, and answered it in how to check I'm inside a specialized function or class

    I used a reverse lookup table - SpecializedKey is a specialized class which equals all other instances with the same specialization, so I can perform a check like this

    def onlyBytes[@specialized E](arg :E) :Option[E] =
        if (specializationFor[E]==specializationFor[Byte]) Some(arg)
        else None
    

    Of course, there's no performance benefit when working with individual primitive values, but with collections, especially iterators, it becomes useful.

    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)
    }
    

提交回复
热议问题