Как запустить и различные пути кода на основе специализации

При использовании такой среды, как 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)
  }
}

1 ответ

Решение

Как уже объяснялось в этом вопросе, вы можете инкапсулировать специализированную реализацию в классе типов. Это будет выглядеть более или менее как следующий код.

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 нужно будет в штучной упаковке.

Другие вопросы по тегам