- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我目前正在使用宏,也许这不是一个好主意,但这是我的问题:
我有以下宏:
def using[A <: { def close(): Unit }, B](resource: A)(f: A => B) = macro usingImpl[A, B]
def usingImpl[A <: { def close(): Unit }, B](c: Context)(resource: c.Expr[A])(f: c.Expr[A => B]): c.Expr[B] = {
import c.universe._
f.tree match {
case Function(params, body) =>
//val ValDef(modifiers, name, tpt, _) = params.head
c.Expr[B](
Block(
List(
//ValDef(modifiers, name, tpt, resource.tree)
ValDef(params.head.symbol, resource.tree)
),
body
)
)
case _: Select =>
reify {
val res = resource.splice
try {
f.splice(res)
} finally {
res.close()
}
}
}
}
如果是Select
,我只需调用该函数并关闭资源,就可以正常工作。但对于 Function
来说,我想将参数值分配给资源并调用主体。当我使用已弃用的 ValDef
创建器时,它需要一个 Symbol
和一个 Tree
,一切正常。如果我使用注释外的 4-args 创建器,则会收到编译器错误,指出值 x$1
不在范围内。当我查看两个版本生成的代码时,它看起来完全相同:
Expr[Int]({
<synthetic> val x$1: Test.Foo = new Test.this.Foo();
x$1.bar.+(23)
})
是否有一种方法可以简单地使用 params.head
并分配一个值?感谢您的帮助!
编辑:
我这样调用宏:
object Test extends App {
import Macros._
class Foo {
def close() {}
def bar = 3
}
println(using(new Foo)(_.bar + 3))
}
正如我所说,如果我使用注释掉的版本,它会给我一个编译器错误,打印 AST 并在最后显示此消息:[error] 符号值 x$1 不存在于测试$delayedInit$body.apply
我使用的是 2.10.1。
最佳答案
啊,现在我可以重现你的错误了。任何时候你得到“这个条目似乎已经杀死了编译器”。消息并在堆栈跟踪中看到类似这样的行:
at scala.reflect.internal.SymbolTable.abort(SymbolTable.scala:49)
您的下一步应该是开始在 c.resetAllAttrs
中包装内容。老实说,我第一次无法重现您的错误的原因是因为我在复制和粘贴后将 block 中的 body
替换为 c.resetAllAttrs(body)
你的代码,甚至不假思索。此时这只是一种条件反射。
例如参见 this little single abstract method class demo对于需要使用此技巧的地方的类似实例。
就您而言,如果我们有:
import scala.language.experimental.macros
import scala.reflect.macros.Context
object Macros {
def using[A <: { def close(): Unit }, B](resource: A)(f: A => B) =
macro usingImpl[A, B]
def usingImpl[A <: { def close(): Unit }, B](c: Context)
(resource: c.Expr[A])(f: c.Expr[A => B]): c.Expr[B] = {
import c.universe._
val expr = f.tree match {
case Function(ValDef(modifiers, name, tpt, _) :: Nil, body) =>
c.Expr[B](
Block(
ValDef(modifiers, name, tpt, resource.tree) :: Nil,
c.resetAllAttrs(body)
)
)
case _: Select => reify {
val res = resource.splice
try { f.splice(res) } finally { res.close() }
}
}
println(expr)
expr
}
}
编译您的测试代码时,我们将看到以下内容:
Expr[B]({
<synthetic> val x$1: $line3.$read.$iw.$iw.Test.Foo = new Test.this.Foo();
x$1.bar.$plus(3)
})
完全符合要求。
关于Scala 宏分配解构函数的参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16451060/
C语言sscanf()函数:从字符串中读取指定格式的数据 头文件: ?
最近,我有一个关于工作预评估的问题,即使查询了每个功能的工作原理,我也不知道如何解决。这是一个伪代码。 下面是一个名为foo()的函数,该函数将被传递一个值并返回一个值。如果将以下值传递给foo函数,
CStr 函数 返回表达式,该表达式已被转换为 String 子类型的 Variant。 CStr(expression) expression 参数是任意有效的表达式。 说明 通常,可以
CSng 函数 返回表达式,该表达式已被转换为 Single 子类型的 Variant。 CSng(expression) expression 参数是任意有效的表达式。 说明 通常,可
CreateObject 函数 创建并返回对 Automation 对象的引用。 CreateObject(servername.typename [, location]) 参数 serv
Cos 函数 返回某个角的余弦值。 Cos(number) number 参数可以是任何将某个角表示为弧度的有效数值表达式。 说明 Cos 函数取某个角并返回直角三角形两边的比值。此比值是
CLng 函数 返回表达式,此表达式已被转换为 Long 子类型的 Variant。 CLng(expression) expression 参数是任意有效的表达式。 说明 通常,您可以使
CInt 函数 返回表达式,此表达式已被转换为 Integer 子类型的 Variant。 CInt(expression) expression 参数是任意有效的表达式。 说明 通常,可
Chr 函数 返回与指定的 ANSI 字符代码相对应的字符。 Chr(charcode) charcode 参数是可以标识字符的数字。 说明 从 0 到 31 的数字表示标准的不可打印的
CDbl 函数 返回表达式,此表达式已被转换为 Double 子类型的 Variant。 CDbl(expression) expression 参数是任意有效的表达式。 说明 通常,您可
CDate 函数 返回表达式,此表达式已被转换为 Date 子类型的 Variant。 CDate(date) date 参数是任意有效的日期表达式。 说明 IsDate 函数用于判断 d
CCur 函数 返回表达式,此表达式已被转换为 Currency 子类型的 Variant。 CCur(expression) expression 参数是任意有效的表达式。 说明 通常,
CByte 函数 返回表达式,此表达式已被转换为 Byte 子类型的 Variant。 CByte(expression) expression 参数是任意有效的表达式。 说明 通常,可以
CBool 函数 返回表达式,此表达式已转换为 Boolean 子类型的 Variant。 CBool(expression) expression 是任意有效的表达式。 说明 如果 ex
Atn 函数 返回数值的反正切值。 Atn(number) number 参数可以是任意有效的数值表达式。 说明 Atn 函数计算直角三角形两个边的比值 (number) 并返回对应角的弧
Asc 函数 返回与字符串的第一个字母对应的 ANSI 字符代码。 Asc(string) string 参数是任意有效的字符串表达式。如果 string 参数未包含字符,则将发生运行时错误。
Array 函数 返回包含数组的 Variant。 Array(arglist) arglist 参数是赋给包含在 Variant 中的数组元素的值的列表(用逗号分隔)。如果没有指定此参数,则
Abs 函数 返回数字的绝对值。 Abs(number) number 参数可以是任意有效的数值表达式。如果 number 包含 Null,则返回 Null;如果是未初始化变量,则返回 0。
FormatPercent 函数 返回表达式,此表达式已被格式化为尾随有 % 符号的百分比(乘以 100 )。 FormatPercent(expression[,NumDigitsAfterD
FormatNumber 函数 返回表达式,此表达式已被格式化为数值。 FormatNumber( expression [,NumDigitsAfterDecimal [,Inc
我是一名优秀的程序员,十分优秀!