我试图调用Shapeless
从内宏quasiquote
用Scala
,我没有得到什么,我想获得.
我的宏不会返回任何错误,但它不会扩展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) 这个问题与我之前的问题的动机相似(虽然它是关于我在不同背景下遇到的问题).
在没有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) 我是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?
谢谢你的帮助.
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) 我正在玩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 …
我想用宏转换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值呢?
我想回答这个问题.
而不是写:
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
有办法解决这个问题吗?我错过了什么?
谢谢你看看,朱利安
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) 我有一个表面上很简单的宏观问题,我已经用头撞了几个小时,但没有运气。也许有更多经验的人可以提供帮助。
我有以下宏:
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) 以下宏粘贴自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 ×10
scala-macros ×9
macros ×4
case-class ×1
constructor ×1
expression ×1
scala-xml ×1
scalac ×1
shapeless ×1