一个用例需要在运行时比较两个类型参数的实际类型。用TypeTag
可能很容易做到这一点,但在scala-3中不推荐使用。因此,我尝试用TypeTest
,但它要求存在该类型的示例,而我没有。因此,我实现了TypeId
。我自己的TypeTag
版本。它的限制和简单程度更高。它只支持类型比较,并且只有在每个涉及的类型都存在TypeId
的单个示例时才能工作。
import scala.collection.{mutable, immutable}
object TypeId {
private var idSequencer: Int = 0
private val typeIds: mutable.HashMap[Int, TypeId[?]] = mutable.HashMap.empty
private def registerNew[A](tm: TypeId[A]): Int = this.synchronized {
idSequencer += 1
typeIds.put(idSequencer, tm)
idSequencer
}
def knownTypeIds: immutable.HashMap[Int, TypeId[?]] = this.synchronized(immutable.HashMap.from(typeIds))
}
trait TypeId[A] {
val id: Int = registerNew(this)
def equalsTo(that: TypeId[?]): Boolean = this.id == that.id
}
正如您所看到的,它要求同步是线程安全的,这是不方便的;并且knownTypeIds
的值易受竞争条件的影响。
我想知道是否有可能在编译时使用宏来创建唯一id。我想要做到这一点,我需要某种编译时全局变量来实现sequencer。scala-3宏是否支持编译时全局变量或替代方案来实现我的目标?
**EDIT:**在提出我的问题几分钟后,我想出了一个非常简单的方法来实现我的目标,即把标识符变成一个带有类型扩展名的字符串。这样的名称可以很容易地在宏中生成。然而,我把这个问题留给了scala-3宏是否支持编译时全局变量。
下面的代码使用类型的名称而不是顺序整数来实现我的目标。
第一次
1条答案
按热度按时间c9x0cxw01#
这将是一个非常糟糕的主意,因为增量编译-很难准确地告诉什么将被编译或者什么时候被编译。你可以很容易地得到一些在
clean
编译上工作的东西,但是在开发期间的部分重新编译上失败,因为不是每一位应该触发序列器的代码都被激发。(我不确定这是否可行,可能还有其他原因需要避免,但这是避免在宏中使用任何命令式代码的一般原因。)