Я в настоящее время играю немного с макросами и, возможно, что это плохая идея, так или иначе, но вот моя проблема:Scala макросов назначение параметров из деконструированного функции
У меня есть следующий макрос:
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] symbol value x$1 does not exist in Test$delayedInit$body.apply
И я использую 2.10.1.
Декомпозиция 'params.head' должна работать отлично: я не могу воспроизвести вашу ошибку (с 2.10.0 или 2.10.1) и на самом деле получить ошибку компилятора с раскомментированной версией. Можете ли вы опубликовать код, который вы используете, для вызова макроса? –
обновил мой вопрос – drexin
Вы пытались превратить деструкторов в Scala? Отличная идея! –