As I’m sure you’re all aware, with Scala 3 we have a new macro system that is focused on generating expressions only, as opposed to Scala 2 macros which were able to generate new definitions that changed the state of the program for everything else.
This has resulted in many requests for the addition of features similar to what annotation macros in Scala 2 provided.
I’m hoping that in this thread we can discuss the various uses of Scala 2 macros, and if there are alternatives that Scala 3 can provide us without having to introduce something like macro annotations in Scala 2.
To start with, there’s the generation of monomorphic service accessors for ZIO 2.
The usage of this macro is as follows:
@accessible
trait ServiceA {
def method(input: Something): UIO[Unit]
}
generates
object ServiceA {
def method(input: Something) =
ZIO.serviceWithZIO[ServiceA](_.method(input))
}
In Scala 3, similar functionality can be achieved with programmatic structural types and regular macros:
trait ServiceA derives MonoService:
def method(input: Something): UIO[Unit]
Service.instance[ServiceA] //produces ServiceBacking { def method(input: Something): ZIO[ServiceA, Nothing, Unit] }
The implementation of MonoService could be something like what’s shown in this repository: GitHub - markehammons/zio-macro-scala3-example
I’m hoping with this thread the community can settle on what are the current weaknesses of macros in Scala 3, what might need added to help things (like facilities for templating), etc.