标签: scala-quasiquotes

如何在Quasiquote中使用Shapeless?

我试图调用Shapeless从内宏quasiquoteScala,我没有得到什么,我想获得.

我的宏不会返回任何错误,但它不会扩展Witness(fieldName)Witness.Lt[String]

val implicits = schema.fields.map { field =>
  val fieldName:String = field.name
  val fieldType = TypeName(field.valueType.fullName)
  val in = TermName("implicitField"+fieldName)
  val tn = TermName(fieldName)
  val cc = TermName("cc")
  q"""implicit val $in = Field.apply[$className,$fieldType](Witness($fieldName), ($cc:   $className) => $cc.$tn)"""
}
Run Code Online (Sandbox Code Playgroud)

这是我的Field定义:

sealed abstract class Field[CC, FieldName] {
  val  fieldName: String
  type fieldType

  // How to extract this field
  def  get(cc : CC) : fieldType
}

object Field {
  // fieldType …
Run Code Online (Sandbox Code Playgroud)

scala shapeless scala-macros scala-quasiquotes

272
推荐指数
1
解决办法
6966
查看次数

在Scala中匹配函数文字与quasiquotes

这个问题与我之前的问题的动机相似(虽然它是关于我在不同背景下遇到的问题).

在没有quasiquotes的情况下,我可以非常轻松地在函数文字上进行模式匹配:

import scala.reflect.macros.Context
import scala.language.experimental.macros

object QQExample {
  def funcDemo(f: Int => String) = macro funcDemo_impl
  def funcDemo_impl(c: Context)(f: c.Expr[Int => String]) = {
    import c.universe._

    f.tree match {
      case Function(ps, body) => List(ps, body) foreach println
      case _ => c.abort(
        c.enclosingPosition,
        "Must provide a function literal."
      )
    }

    c.literalUnit
  }
}
Run Code Online (Sandbox Code Playgroud)

其工作方式如下:

scala> QQExample.funcDemo((a: Int) => a.toString)
List(val a: Int = _)
a.toString()
Run Code Online (Sandbox Code Playgroud)

现在假设我想使用quasiquotes更灵活地进行相同类型的匹配.以下内容也将匹配该功能,并打印出我们期望的内容.

case q"($x: $t) => $body" => List(x, t, body) foreach …
Run Code Online (Sandbox Code Playgroud)

macros scala scala-macros scala-quasiquotes

27
推荐指数
1
解决办法
2599
查看次数

Scala quasiquote concatenation

我是scala宏的新手,我花了几天时间试着写第一篇.我有quasiquotes连接问题.

有一个案例条款列表,让我们说如下:

val cases = cq"x => 1 " :: cq"_ => 0 " :: Nil
Run Code Online (Sandbox Code Playgroud)

我需要从中构建一个部分功能.问题是我不知道如何将它们粘贴到最终的quasiquote中.文档说我应该做这样的事情:

q"{ case ..$cases }"
Run Code Online (Sandbox Code Playgroud)

但如果我这样做,它就不起作用.

有没有办法从这样的列表构建PartialFunction?

谢谢你的帮助.

scala scala-macros scala-quasiquotes

9
推荐指数
1
解决办法
701
查看次数

多参数和参数列表的准引号

Quasiquotes非常棒 - 它们使得Scala中的宏写得非常痛苦,而且根据我的经验,它们几乎总是按照我的预期完成工作.最重要的是,它们现在可以作为 Scala 2.10中的插件使用.

这个问题是关于我在写这篇博文时遇到的一个小问题.当我找到几分钟时,我会在我的列表中查看,但我想我会在这里发布它以防万一其他人可以打败我,并帮助其他人遇到同样的问题.

假设我有一个名称类型对的列表列表:

val pss = List(
  List(newTermName("x") -> typeOf[Int], newTermName("y") -> typeOf[Char]),
  List(newTermName("z") -> typeOf[String])
)
Run Code Online (Sandbox Code Playgroud)

我想把它们变成一棵看起来像这样的树:

def foo(x: Int, y: Char)(z: String) = ???
Run Code Online (Sandbox Code Playgroud)

以下工作正常:

q"def bar(${pss.head.head._1}: ${pss.head.head._2}) = ???"
Run Code Online (Sandbox Code Playgroud)

也就是说,它构建了以下树:

def bar(x: Int) = ???
Run Code Online (Sandbox Code Playgroud)

这表明我应该能够写出这样的东西:

val quoted = pss.map(_.map { case (n, t) => q"$n: $t" })

q"def foo..${quoted.map(ps => q"($ps)")} = 1"
Run Code Online (Sandbox Code Playgroud)

或者更简单,在单个参数列表中有多个参数:

q"def baz(..${quoted.head}) = ???"
Run Code Online (Sandbox Code Playgroud)

两者都不起作用 - 我得到这样的错误:

<console>:28: error: type mismatch;
 found …
Run Code Online (Sandbox Code Playgroud)

macros scala scala-macros scala-quasiquotes

8
推荐指数
1
解决办法
1315
查看次数

将传递的函数体拼接成宏重写的表达式

我正在玩Scala 2.11的新宏功能.我想看看我是否可以进行以下重写:

forRange(0 to 10) { i => println(i) }

// into

val iter = (0 to 10).iterator
while (iter.hasNext) {
  val i = iter.next
  println(i)
}
Run Code Online (Sandbox Code Playgroud)

我认为我对这个宏非常接近:

def _forRange[A](c: BlackboxContext)(range: c.Expr[Range])(func: c.Expr[Int => A]): c.Expr[Unit] = {
  import c.universe._

  val tree = func.tree match {
    case q"($i: $t) => $body" => q"""
        val iter = ${range}.iterator
        while (iter.hasNext) {
          val $i = iter.next
          $body
        }
      """
    case _ => q""
  }

  c.Expr(tree)
}
Run Code Online (Sandbox Code Playgroud)

调用时会产生以下输出forRange(0 to 10) { i …

macros expression scala scala-macros scala-quasiquotes

8
推荐指数
2
解决办法
785
查看次数

在Scala宏中匹配XML文字

我想用宏转换Scala XML文字.(不是带XML的字符串文字,而是实际的XML文字).据我所知,XML文字实际上并没有构建在AST级别的语言中,而是在解析器中被贬低.有趣的是,这确实有效:

case q"<specificTag></specificTag>" => ... // succeeds for specificTag with no
                                           // attributes and children
Run Code Online (Sandbox Code Playgroud)

但显然,这完全没用,因为不可能以任意方式匹配任意xml.就像是

case q"<$prefix:$label ..$attrs>$children</$prefix:$label>" => ...
Run Code Online (Sandbox Code Playgroud)

无法工作,因为我们必须在模式中绑定相同的变量两次.

打印出这样的xml文字表达式的树实际上给出了desugared版本.例如.

new _root_.scala.xml.Elem(null,"specificTag",_root_.scala.xml.Null,$scope,false)
Run Code Online (Sandbox Code Playgroud)

但尝试匹配此失败:

case q"new _root_.scala.xml.Elem(..$params)" => ... // never succeeds
Run Code Online (Sandbox Code Playgroud)

我很迷惑!我的问题是:有没有办法可靠地匹配scala宏中的任意xml litarals?另外:为什么它们在quasiquotes中支持常量xml而不是desugared值呢?

scala scala-xml scala-macros scala-quasiquotes

8
推荐指数
1
解决办法
481
查看次数

如何使用宏注释向Scala案例类添加无参数构造函数?

我想回答这个问题.

而不是写:

case class Person(name: String, age: Int) {
  def this() = this("",1)
}
Run Code Online (Sandbox Code Playgroud)

我以为我会使用宏注释来扩展它:

@Annotation
case class Person(name: String, age: Int)
Run Code Online (Sandbox Code Playgroud)

所以我尝试DefDef在宏注释的impl中使用quasiquotes 将新构造函数添加为普通的,如:

val newCtor = q"""def this() = this("", 1)"""
val newBody = body :+ newCtor
q"$mods class $name[..$tparams](..$first)(...$rest) extends ..$parents { $self => ..$newBody }"
Run Code Online (Sandbox Code Playgroud)

但是这会返回一个错误: called constructor's definition must precede calling constructor's definition

有办法解决这个问题吗?我错过了什么?

谢谢你看看,朱利安

constructor scala case-class scala-macros scala-quasiquotes

7
推荐指数
1
解决办法
1707
查看次数

How does the Scala compiler perform implicit conversion?

I have a custom class, A, and I have defined some operations within the class as follows:

def +(that: A) = ...
def -(that: A) = ...
def *(that: A) = ...

def +(that: Double) = ...
def -(that: Double) = ...
def *(that: Double) = ...
Run Code Online (Sandbox Code Playgroud)

In order to have something like 2.0 + x make sense when x is of type A, I have defined the following implicit class:

object A {
  implicit class Ops (lhs: …
Run Code Online (Sandbox Code Playgroud)

scala scalac scala-compiler scala-quasiquotes

7
推荐指数
1
解决办法
182
查看次数

如何获取传递给 Scala 宏的参数的运行时值?

我有一个表面上很简单的宏观问题,我已经用头撞了几个小时,但没有运气。也许有更多经验的人可以提供帮助。

我有以下宏:

import scala.language.experimental.macros
import scala.reflect.macros.blackbox.Context

object MacroObject {
  def run(s: String): Unit =
    macro runImpl

  def runImpl(c: Context)(s: c.Tree): c.Tree = {
    import c.universe._
    println(s)    // <-- I need the macro to know the value of s at compile time
    q"()"
  }
}
Run Code Online (Sandbox Code Playgroud)

问题是:我希望宏知道s传递给它的值——不是 AST s,而是s它本身的值。具体来说,我希望它具有这种行为:

def runTheMacro(str: String): Unit = MacroObject.run(str)

final val HardCodedString1 = "Hello, world!"
runTheMacro(HardCodedString1)    // the macro should print "Hello, world!"
                                 // to the console during macro expansion …
Run Code Online (Sandbox Code Playgroud)

macros scala scala-macros scala-quasiquotes scala-reflect

6
推荐指数
1
解决办法
528
查看次数

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
查看次数