如何 运行 和基于专业化的不同代码路径
How to Run and Different Code Paths Based on Specialisation
在将 FastUtils 这样的框架与 Scala 一起使用时,由于框架本身具有专门的数据结构,您如何根据有效的专业化生成适当的代码?即,您如何以编程方式找出正在专门化的内容并执行适当的代码?那么在这种情况下你如何处理与路径相关的类型。
对于objects
class Container[@specialized T](var window: Int) {
val data = new ObjectArrayList[T](window)
}
对于 char
我希望它是:
class Container[@specialized T](var window: Int) {
val data = new CharArrayList(window)
}
但这要建立在T
的专业化基础上。如果我换一种说法,sudo 代码可能会像
class Container[@specialized T](var window: Int) {
val data = specialisationOf(T) match {
case "Char" => new CharArrayList(window)
case "Int" => new IntegerArrayList(window)
...
...
...
case _ => new ObjectArrayList[T](window)
}
}
如 this question 中所述,您可以将专用实现封装在类型类中。这看起来或多或少像下面的代码。
import it.unimi.dsi.fastutil.ints.IntArrayList
import it.unimi.dsi.fastutil.chars.CharArrayList
import it.unimi.dsi.fastutil.objects.ObjectArrayList
class Container[@specialized(Int,Char) T](window: Int)(implicit impl: ContainerImpl[T]) {
impl.init(window)
def add(element: T) = impl.add(element)
override def toString = impl.toString
}
trait ContainerImpl[@specialized(Int,Char) T] {
def init(window: Int): Unit
def add(element: T): Unit
def toString: String
}
object ContainerImpl extends LowerPriorityImplicits {
implicit def intContainer = new ContainerImplInt
implicit def charContainer = new ContainerImplChar
}
trait LowerPriorityImplicits {
implicit def anyContainer[T] = new ContainerImplT[T]
}
final class ContainerImplInt extends ContainerImpl[Int] {
var data: IntArrayList = _
def init(window: Int) = data = new IntArrayList(window)
def add(element: Int) = data.add(element)
override def toString = data.toString
}
final class ContainerImplChar extends ContainerImpl[Char] {
var data: CharArrayList = _
def init(window: Int) = data = new CharArrayList(window)
def add(element: Char) = data.add(element)
override def toString = data.toString
}
final class ContainerImplT[T] extends ContainerImpl[T] {
var data: ObjectArrayList[T] = _
def init(window: Int) = data = new ObjectArrayList(window)
def add(element: T) = data.add(element)
override def toString = data.toString
}
请注意,尽管 add
的实现看起来总是一样的,但在 data
上调用的方法每次都是不同的重载。如果您以更多态的方式编写此代码,则不会选择最具体的 add
方法,并且您的 Int
或 Char
将需要装箱。
在将 FastUtils 这样的框架与 Scala 一起使用时,由于框架本身具有专门的数据结构,您如何根据有效的专业化生成适当的代码?即,您如何以编程方式找出正在专门化的内容并执行适当的代码?那么在这种情况下你如何处理与路径相关的类型。
对于objects
class Container[@specialized T](var window: Int) {
val data = new ObjectArrayList[T](window)
}
对于 char
我希望它是:
class Container[@specialized T](var window: Int) {
val data = new CharArrayList(window)
}
但这要建立在T
的专业化基础上。如果我换一种说法,sudo 代码可能会像
class Container[@specialized T](var window: Int) {
val data = specialisationOf(T) match {
case "Char" => new CharArrayList(window)
case "Int" => new IntegerArrayList(window)
...
...
...
case _ => new ObjectArrayList[T](window)
}
}
如 this question 中所述,您可以将专用实现封装在类型类中。这看起来或多或少像下面的代码。
import it.unimi.dsi.fastutil.ints.IntArrayList
import it.unimi.dsi.fastutil.chars.CharArrayList
import it.unimi.dsi.fastutil.objects.ObjectArrayList
class Container[@specialized(Int,Char) T](window: Int)(implicit impl: ContainerImpl[T]) {
impl.init(window)
def add(element: T) = impl.add(element)
override def toString = impl.toString
}
trait ContainerImpl[@specialized(Int,Char) T] {
def init(window: Int): Unit
def add(element: T): Unit
def toString: String
}
object ContainerImpl extends LowerPriorityImplicits {
implicit def intContainer = new ContainerImplInt
implicit def charContainer = new ContainerImplChar
}
trait LowerPriorityImplicits {
implicit def anyContainer[T] = new ContainerImplT[T]
}
final class ContainerImplInt extends ContainerImpl[Int] {
var data: IntArrayList = _
def init(window: Int) = data = new IntArrayList(window)
def add(element: Int) = data.add(element)
override def toString = data.toString
}
final class ContainerImplChar extends ContainerImpl[Char] {
var data: CharArrayList = _
def init(window: Int) = data = new CharArrayList(window)
def add(element: Char) = data.add(element)
override def toString = data.toString
}
final class ContainerImplT[T] extends ContainerImpl[T] {
var data: ObjectArrayList[T] = _
def init(window: Int) = data = new ObjectArrayList(window)
def add(element: T) = data.add(element)
override def toString = data.toString
}
请注意,尽管 add
的实现看起来总是一样的,但在 data
上调用的方法每次都是不同的重载。如果您以更多态的方式编写此代码,则不会选择最具体的 add
方法,并且您的 Int
或 Char
将需要装箱。