DenisNovac
DenisNovac

Reputation: 728

Scala 3: inline vs quoted (macros)

Recently i had an experience of writing a macros in Scala 3. I used inline for simple function and quoted code with scala.quoted for more complex operation.

It seems that both of this features replace some runtime code with compile-time generated code, but inline has some restrictions.

What is the differences between them and why inline can't be used instead of quoted code everywhere?

Upvotes: 2

Views: 407

Answers (1)

gianluca aguzzi
gianluca aguzzi

Reputation: 1724

TL;DR inline is a mechanism that replaces function call with its complete body at compile-time (a form of optimisation). In Scala, it is used also to write macros, i.e. function that will be evaluated at compile-time that could manipulate the AST Scala code. scala.quoted contains functions to write macros using quasiquoting (a neat notation that lets you manipulate Scala syntax trees with ease) and splicing (inverse operator of quasiquoting) operator. In general, they are used together to create compile-time metaprogramming. Indeed, inline is the enabling mechanism and scala.quoted gives some functionalities to manipulate and evaluate Scala AST. When you can't infer something at compile time (or you want to generate code at runtime), you can't use inline, and you should use scala.quoted solely.

Inlining is a mechanism used to inline code instead of performing function call. So, for example:

inline def foo : Int = 3
foo

became something like this

inline def foo : Int = 3
3

This mechanism is introduced also by other languages (as Kotlin), but in the Scala language has another relevant feature: during the inline expansion, the compiler could perform further compile-time operations to manipulate the inline output process. A form of compile-metaprogramming could be perform using inline condition and inline match:

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

This code thrown an exception (at compile time) if you pass as argument a "hello" for example.

Instead scala.qouted contains operators to manipulate Scala AST: quoting (Quasiquotes are a neat notation that lets you manipulate Scala syntax trees with ease:) and splicing (inverse operator of quasiqoute). Theoretically, those operators could be used at runtime (with the new TASTy structure) and at compile time (using inline). As stated here, the relations between inline and quoting is:

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.

Sometimes, you are forced to use runtime expansion because some information can't be inferred at compile-time or because you want to generate code at runtime. So you can use quoting for Runtime Multi-Stage Programming and TASTy Inspection.

I hope I give you a clearer vision and useful links to explore deeper these fascinating topics.

Upvotes: 7

Related Questions