斯卡拉 3 : inline vs quoted (macros)

标签 scala metaprogramming scala-macros

最近我有在 Scala 3 中编写宏的经验。我使用 inline 进行简单的功能,并使用 scala.quoted 引用代码进行更复杂的操作。

似乎这两个特性都用编译时生成的代码替换了一些运行时代码,但是inline有一些限制。

它们之间有什么区别,为什么不能在任何地方使用 inline 代替引用代码?

最佳答案

TL;DR inline 是一种在编译时用函数调用的完整主体替换函数调用的机制(一种优化形式)。在 Scala 中,它还用于编写宏,即将在编译时评估的函数,可以操作 AST Scala 代码。 scala.quoted 包含使用准引用(一种简洁的符号,让您轻松操作 Scala 语法树)和拼接(准引用的逆运算符)运算符编写宏的函数。通常,它们一起用于创建编译时元编程。 事实上,inline 是启用机制,scala.quoted 提供了一些操作和评估 Scala AST 的功能。当你不能在编译时推断出某些东西(或者你想在运行时生成代码)时,你不能使用内联,你应该单独使用 scala.quoted。

内联是一种用于内联代码而不是执行函数调用的机制。 所以,例如:

inline def foo : Int = 3
foo

变成了这样

inline def foo : Int = 3
3

其他语言(如 Kotlin)也引入了这种机制,但在 Scala 语言中还有一个相关的特性:在内联扩展期间,编译器可以执行进一步的编译时操作来操纵内联输出过程。 可以使用内联条件和内联匹配执行一种编译元编程形式:

inline acceptString(value : String) : Boolean = inline match {
    case "name" => true
    case "other" => false
    case _ => error("error thrown at compile time")
}

例如,如果您将 "hello" 作为参数传递,此代码将抛出异常(在编译时)。

scala.qouted 包含操作 Scala AST 的运算符:引用(Quasiquotes 是一种简洁的符号,可让您轻松操作 Scala 语法树:) 和拼接(quasiqoute 的逆运算符)。理论上,这些运算符可以在运行时(使用新的 TASTy 结构)和编译时(使用 inline)使用。 如前所述 here ,内联和引用的关系是:

Seen by itself, principled metaprogramming looks more like a framework for runtime metaprogramming than one for compile-time metaprogramming with macros. But combined with Scala 3’s inline feature it can be turned into a compile-time system. The idea is that macro elaboration can be understood as a combination of a macro library and a quoted program.

有时,您不得不使用运行时扩展,因为某些信息无法在编译时推断出来,或者因为您想在运行时生成代码。所以你可以对 Runtime Multi-Stage Programming 使用引号和 TASTy Inspection .

我希望我能为您提供更清晰的视野和有用的链接,以更深入地探索这些引人入胜的主题。

关于斯卡拉 3 : inline vs quoted (macros),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67208932/

相关文章:

scala - 动态创建案例类

斯卡拉动力学 : Ability to add dynamic methods?

Scala Swing 日期选择器

scala - 如何在 Scala 中将 Nil 识别为 List 类中的方法

java - 在 Java 中运行时省略实例字段

c++ - SFINAE C++ 方法检查

python - 转换类名中的字符串(从 appengine 数据存储到类)

scala - Scala 中的准引用和泛型

python - 如何在以下示例中使用 pyspark 折叠操作找到最大值?

scala - 从两个 boolean 值构建字符串