scala-3宏支持编译时全局变量吗?如何使用它们?

btxsgosb  于 2022-11-23  发布在  Scala
关注(0)|答案(1)|浏览(108)

一个用例需要在运行时比较两个类型参数的实际类型。用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宏是否支持编译时全局变量。

下面的代码使用类型的名称而不是顺序整数来实现我的目标。
第一次

c9x0cxw0

c9x0cxw01#

这将是一个非常糟糕的主意,因为增量编译-很难准确地告诉什么将被编译或者什么时候被编译。你可以很容易地得到一些在clean编译上工作的东西,但是在开发期间的部分重新编译上失败,因为不是每一位应该触发序列器的代码都被激发。
(我不确定这是否可行,可能还有其他原因需要避免,但这是避免在宏中使用任何命令式代码的一般原因。)

相关问题