diff --git a/scala-core-modules/scala-core-9/README.md b/scala-core-modules/scala-core-9/README.md index 8b472c65a..9e6cdf898 100644 --- a/scala-core-modules/scala-core-9/README.md +++ b/scala-core-modules/scala-core-9/README.md @@ -6,4 +6,4 @@ - [Find Two’s Complement of a Number in Scala](https://www.baeldung.com/scala/compute-twos-complement) - [Convert Option to Either in Scala](https://www.baeldung.com/scala/option-either-conversion) - [Meaning of _root_ In Scala Import Clause](https://www.baeldung.com/scala/root-import-clause) -- [Check if All Characters in a Scala String Are Either Upper or Lower Case](https://www.baeldung.com/scala/string-check-all-characters-upper-lower-case) +- [Check if All Characters in a Scala String Are Either Upper or Lower Case](https://www.baeldung.com/scala/string-check-all-characters-upper-lower-case diff --git a/scala-core-modules/scala-core-9/src/main/scala/com/baeldung/scala/tastyfiles/PowerMacro.scala b/scala-core-modules/scala-core-9/src/main/scala/com/baeldung/scala/tastyfiles/PowerMacro.scala new file mode 100644 index 000000000..be3da7db8 --- /dev/null +++ b/scala-core-modules/scala-core-9/src/main/scala/com/baeldung/scala/tastyfiles/PowerMacro.scala @@ -0,0 +1,30 @@ +package com.baeldung.scala.tastyfiles + +import scala.quoted.* + +object PowerMacro: + // The macro that unrolls the computation of powers and then generates the expression + inline def showAsPowerTerm(inline x: Double, n: Int): String = ${ + showAsTermImpl('x, 'n) + } + + // The actual implementation of the macro + private def showAsTermImpl(x: Expr[Double], n: Expr[Int])(using + Quotes + ): Expr[String] = + import quotes.reflect.* + + n.value match + case Some(num) => + val powerExpr = unrolledPowerCode(x, num) + Expr( + powerExpr.asTerm.toString + ) // Ensures that the asTerm method call is evaluated at compile-time + case None => + '{ "Error: 'n' must be a known constant at compile time." } + + // Helper method to unroll the power computation + def unrolledPowerCode(x: Expr[Double], n: Int)(using Quotes): Expr[Double] = + if n == 0 then '{ 1.0 } + else if n == 1 then x + else '{ $x * ${ unrolledPowerCode(x, n - 1) } } diff --git a/scala-core-modules/scala-core-9/src/test/scala/com/baeldung/scala/tastyfiles/PowerMacroTest.scala b/scala-core-modules/scala-core-9/src/test/scala/com/baeldung/scala/tastyfiles/PowerMacroTest.scala new file mode 100644 index 000000000..fa5093073 --- /dev/null +++ b/scala-core-modules/scala-core-9/src/test/scala/com/baeldung/scala/tastyfiles/PowerMacroTest.scala @@ -0,0 +1,15 @@ +package com.baeldung.scala.tastyfiles + +import com.baeldung.scala.tastyfiles.* + +import org.scalatest.flatspec.AnyFlatSpec +import org.scalatest.matchers.should.Matchers + +class PowerMacroUnitTest extends AnyFlatSpec with Matchers: + + "PowerMacro.showAsPowerTerm" should "generate compile-time term structure" in: + val expr: String = PowerMacro.showAsPowerTerm(2.0, 3) + + expr == """ + Inlined(Ident(PowerMacro$),List(),Apply(Select(Inlined(EmptyTree,List(),Inlined(EmptyTree,List(),Literal(Constant(2.0)))),*),List(Inlined(EmptyTree,List(),Inlined(Ident(PowerMacro$),List(),Apply(Select(Inlined(EmptyTree,List(),Inlined(EmptyTree,List(),Literal(Constant(2.0)))),*),List(Inlined(EmptyTree,List(),Inlined(EmptyTree,List(),Literal(Constant(2.0))))))))))) + """.trim