【问题标题】:How to Run and Different Code Paths Based on Specialisation如何运行和基于专业化的不同代码路径
【发布时间】:2017-02-09 04:46:18
【问题描述】:

在使用像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)
  }
}

【问题讨论】:

  • 我已经在做手工专业化了。我想做的是用最少的重新定义。感谢您的指针,但这并不能解决我所追求的问题..
  • 您在问题中所写的方式是不可能的,因为不同的 ArrayList 类型没有具有专用方法的通用超类型。在(几乎)每个对data 的方法调用上,您都必须再次执行match 并转换为最具体的类型。这可能只是用装箱开销代替了运行时手动类型比较的开销。

标签: scala collections types specialization fastutil


【解决方案1】:

正如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 方法,而您的 IntChar 将需要被装箱。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-11-15
    • 1970-01-01
    • 2014-10-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多