标签: scala-macros

Scala 文档示例中的“宏实现参考形状错误”

以下宏粘贴自http://docs.scala-lang.org/overviews/quasiquotes/usecases.html

import reflect.macros.Context
import language.experimental.macros
val universe = reflect.runtime.universe; import universe._
import reflect.runtime.currentMirror
import tools.reflect.ToolBox
val toolbox = currentMirror.mkToolBox()

object debug {
  def apply[T](x: =>T): T = macro impl
  def impl(c: Context)(x: c.Tree) = { import c.universe._
    val q"..$stats" = x
    val loggedStats = stats.flatMap { stat =>
      val msg = "executing " + showCode(stat)
      List(q"println($msg)", stat)
    }
    q"..$loggedStats"
  }
}
Run Code Online (Sandbox Code Playgroud)

它在 Scala 2.11.1 中产生此错误消息:

Q.scala:9: error: macro implementation reference has wrong shape. required:
macro [<static object>].<method name>[[<type …
Run Code Online (Sandbox Code Playgroud)

scala scala-macros scala-quasiquotes

5
推荐指数
1
解决办法
1491
查看次数

在运行时访问函数源代码的宏

使用 Scala 宏,我想访问函数 f 的源代码。

这是我的问题的简化示例:

def logFImplementation(f: => Boolean) {
    val sourceCodeOfF: String = ... // <-- how to get source code of f??

    println("Scala source of f=" + sourceCodeOfF)
}
Run Code Online (Sandbox Code Playgroud)

因此对于:

logFImplementation { val i = 5; List(1, 2, 3); true }
Run Code Online (Sandbox Code Playgroud)

它应该打印:

Scala source of f=val i: Int = 5; immutable.this.List.apply[Int](1, 2, 3); true
Run Code Online (Sandbox Code Playgroud)

(现在我测试了宏以在运行时访问源代码文本,它非常有用,{ val i = 5; List(1, 2, 3); true }.logValueImplf.logValueImpl它只是打印f.)

感谢您的任何建议。

reflection macros scala scala-macros

5
推荐指数
2
解决办法
892
查看次数

Scala 宏:使用选项类型创建新类

鉴于此,我想编写一个宏:

@MetaRest case class User(
  @get               id            : Int,
  @get @post @patch  name          : String,
  @get @post         email         : String,
                     registeredOn  : DateTime
)
Run Code Online (Sandbox Code Playgroud)

生成以下代码段:

object User {
  case class Get(id: Int, name: String, email: String)
  case class Post(name: String, email: String
  case class Patch(name: Option[String])   // Note - the Option type here!
}
Run Code Online (Sandbox Code Playgroud)

我在这里取得了不错的进展:https : //github.com/pathikrit/metarest

这是我的尝试:https : //github.com/pathikrit/metarest/blob/master/src/main/scala/com/github/pathikrit/MetaRest.scala

class MetaRest extends StaticAnnotation {
  def macroTransform(annottees: Any*): Any = macro MetaRest.impl
}

object MetaRest {
  sealed trait …
Run Code Online (Sandbox Code Playgroud)

scala scala-macros scala-2.11 scala-macro-paradise scalameta

5
推荐指数
1
解决办法
733
查看次数

如何在 Scala 编译时检查某个 T 是否为 case 类?

我有以下宏:

package macros

import scala.reflect.macros.blackbox.Context

object CompileTimeAssertions {
  def mustBeCaseClass[T]: Unit =
    macro CompileTimeAssertionsImpl.mustBeCaseClass[T]
}

object CompileTimeAssertionsImpl {
  def mustBeCaseClass[T: c.WeakTypeTag](c: Context): c.Expr[Unit] = {
    import c.universe._
    val symbol = c.weakTypeTag[T].tpe.typeSymbol
    if (!symbol.isClass || !symbol.asClass.isCaseClass) {
      c.error(c.enclosingPosition, s"${symbol.fullName} must be a case class")
    }
    reify(Unit)
  }
}
Run Code Online (Sandbox Code Playgroud)

它在不涉及泛型时有效,但在以下情况下失败:

import macros.CompileTimeAssertions._
import org.scalatest.{Matchers, WordSpec}

case class ACaseClass(foo: String, bar: String)

class NotACaseClass(baz: String)

class MacroSpec extends WordSpec with Matchers {
  "the mustBeCaseClass macro" should {
    "compile when passed a case class" …
Run Code Online (Sandbox Code Playgroud)

scala scala-macros scala-2.11

5
推荐指数
1
解决办法
1154
查看次数

动态创建案例类

我正在使用一个 csv 库,它接受一个案例类并将其转换为行供我阅读。

语法非常接近File(path).asCsvReader[caseClass]. 链接到这里的库

然而问题是我想从数据库中的表生成案例类。我可以接收数据库中的表以及列的类型(Int、Long、Double、String 等),但我不知道如何使用该数据动态创建案例类,因为我在编译时不知道这些信息。

正因为如此,我也无法使用宏,因为我不知道宏编译时的表数据。

那么,一旦收到表数据,然后将该案例类传递给 csv 库,我将如何动态创建该案例类?

scala scala-macros slick

5
推荐指数
1
解决办法
1万
查看次数

在编译时列出包中的类

我试图在编译时列出包中的所有类。

让我们定义一个具有以下结构的项目:

com.main
   Main.scala
com.package
   Method.scala
com.package.method1
   Method1.scala
com.package.method2
    Method2.scala
Run Code Online (Sandbox Code Playgroud)

在哪里:

方法.scala

abstract class Method(val name: String) {
}
Run Code Online (Sandbox Code Playgroud)

Method1.scala 和 Method2.scala (更改各自的名称)

class Method1 extends Method(name = "Method1") {
}
Run Code Online (Sandbox Code Playgroud)

我想从 Main.scala 获取 com.package._ 中定义的类列表,如下所示:

object Main() {
    val names = List("Method1", "Method2")
}
Run Code Online (Sandbox Code Playgroud)

我可以对名称进行硬编码(如图所示),但我想知道是否可以在编译时获取这些名称。我知道在运行时可以使用http://software.clapper.org/classutil/

jvm scala scala-macros scala-reflect

5
推荐指数
0
解决办法
269
查看次数

引用注释宏生成的方法时,Scaladoc 生成失败

我有两个类,将它们称为FooFizzFoo使用一个被调用的注释宏expand来为其某些方法创建别名(实际实现所做的不仅仅是创建别名,但简单版本仍然会出现以下问题)。为简单起见,假设expand宏简单地获取带注释的类中的所有方法,并制作它们的副本,将“Copy”附加到方法名称的末尾,然后将调用转发到原始方法。

我的问题是,如果我使用expand宏 on Foo,它会创建一个Foo#bar名为的方法的副本barCopy,当barCopy在另一个类中调用时Fizz,一切都会编译,但 scaladoc 生成失败,如下所示:

[error] ../src/main/scala/Foo.scala:11: value barCopy is not a member of Foo
[error]     def str = foo.barCopy("hey")
[error]                   ^
[info] No documentation generated with unsuccessful compiler run
Run Code Online (Sandbox Code Playgroud)

如果我删除标记正在复制的方法 ( Foo#bar)的 scaladoc ,该sbt doc命令将再次运行。就好像 scaladoc 生成器在不使用启用的宏天堂插件的情况下调用编译器的早期阶段一样,但如果从有问题的方法中删除文档,它会以某种方式工作。

这是expand宏:

import scala.annotation.{ StaticAnnotation, compileTimeOnly }
import scala.language.experimental.macros
import scala.reflect.macros.whitebox.Context

@compileTimeOnly("You must enable the macro …
Run Code Online (Sandbox Code Playgroud)

scala scaladoc scala-macros scala-macro-paradise

5
推荐指数
1
解决办法
471
查看次数

没有同伴的顶级类只能扩展为同名类或包含同名同伴的块

我尝试使用https://github.com/estatico/scala-newtype,如下所示:

import io.estatico.newtype.macros.newtype
import cats._
import io.databaker.env._

@newtype case class DbUrl(v: String)

@newtype case class DbUser(v: String)

@newtype case class DbPw(v: String)

final case class DbParams(url: DbUrl, user: DbUser, pw: DbPw)

trait DbConnector[F[_]] {
  def read(url: DbUrl, user: DbUser, pw: DbPw): F[DbParams]
}


object DbConnector {

  def impl[F[_] : MonadError[*[_], Throwable]](env: Environment[F])
  : DbConnector[F] =
    new LiveDbConnector[F](env)

}
Run Code Online (Sandbox Code Playgroud)

编译器抱怨:

[error] ../db/DbConnector.scala:7:2: top-level class without companion can only expand either into an eponymous class or into a block consisting …
Run Code Online (Sandbox Code Playgroud)

scala scala-macros scala-cats

5
推荐指数
1
解决办法
624
查看次数

在 Scala 宏中,如何从 WeakTypeTag 中检索完整类型信息?

我正在编写宏将类型描述转换为单例类型:

object Type2String {

  def apply[I]: Witness.Lt[String] = macro Macros.apply[I]

  final class Macros(val c: whitebox.Context) extends MWithReflection {

    import c.universe._

    def apply[A: WeakTypeTag]: Tree = {

      val tt: Type = weakTypeOf[A]
      val str = tt.toString

      // val vv = viz(tt)

      q"shapeless.Witness.mkWitness[$str]($str)"
    }
  }
}

Run Code Online (Sandbox Code Playgroud)

问题是因为 A 只有一个 WeakTypeTag。它无法从泛型类型中提取正确的信息:


  case class ^^[T1, T2]() {

    final val wTSelf = Type2String[^^[T1, T2]]
  }


    val e1 = ^^[Int, String]()

    e1.wTSelf
Run Code Online (Sandbox Code Playgroud)

这给出了错误的见证人类型: shapeless.Witness.Aux[String("T1 ^^ T2")]

所以我的问题是:

  1. 现在是编译时,类型信息应该是完全可见的,为什么T1和T2被擦除了?

  2. 如何修复此程序以提供正确的类型信息:

shapeless.Witness.Aux[String("Int ^^ String")]

?

scala scala-macros scala-2.13

5
推荐指数
1
解决办法
132
查看次数

类型类派生访问默认值

使用镜像在 Scala 3 中执行类型类派生时,是否有一种干净的方法来访问案例类字段的默认值?例如:

case class Foo(s: String = "bar", i: Int, d: Double = Math.PI)
Run Code Online (Sandbox Code Playgroud)

Mirror.Product.MirroredElemLabels将被设置为("s", "i", "d")。有没有类似的东西:(Some["bar"], None, Some[3.141592653589793])

如果不能,这可以使用宏来实现吗?我可以同时使用镜像和宏来派生类型类实例吗?

scala typeclass scala-macros generic-derivation scala-3

5
推荐指数
1
解决办法
133
查看次数