【问题标题】:Does scala-3 macros support compile-time global variables? How to use them?scala-3 宏是否支持编译时全局变量?如何使用它们?
【发布时间】:2022-11-22 03:41:15
【问题描述】:

用例需要在运行时比较两个类型参数的实际类型。使用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。我想为此我需要某种编译时全局变量来实现音序器。 scala-3 宏是否支持编译时全局变量或实现我的目标的替代方法?

编辑:问完我的问题几分钟后,我想出了一个非常简单的方法来实现我的目标,方法是将标识符设为带有类型扩展名的字符串。这样的名称可以很容易地在宏中生成。 但是,我想知道 scala-3 宏是否支持编译时全局变量。

【问题讨论】:

    标签: scala scala-macros scala-3


    【解决方案1】:

    这将是一个非常糟糕的主意,因为增量编译 - 很难准确判断将编译什么或何时编译。你可以很容易地得到一些在clean 编译上工作的东西,但是在开发过程中部分重新编译失败,因为并不是应该触发定序器的每一位代码都被触发了。

    (我不确定它是否可行,并且可能有其他原因可以避免它,但这是避免在宏中使用任何类型的命令式代码的一般原因。)

    【讨论】:

    • 也许,如果它们(编译时变量)不是全局的,而是某些工件的本地工件,当它们中的任何一个被触摸时,这些工件会触发重新编译引用它的所有文件。嗯...太多的语言设计工作却很少获得价值。
    猜你喜欢
    • 2017-03-16
    • 2014-08-29
    • 1970-01-01
    • 2011-01-18
    • 2016-08-05
    • 2011-01-24
    • 2016-03-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多