Я играл с новыми функциями макроса 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)
}
Я думаю, что я получил довольно близко с этим макросом:
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)
}
Это дает следующий результат, когда называется forRange(0 to 10) { i => println(i) }
(по крайней мере, это то, что функция show
дает мне на результирующем дереве):
{
val iter = scala.this.Predef.intWrapper(0).to(10).iterator;
while$1(){
if (iter.hasNext)
{
{
val i = iter.next;
scala.this.Predef.println(i)
};
while$1()
}
else
()
}
}
это выглядит, как он должен работать, но есть конфликт между моим определяется вручнуюval i
и i
ссылки в сращивания в теле функции. Я получаю следующее сообщение об ошибке:
ReplGlobal.abort: symbol value i does not exist in$line38.$read$$iw$$iw$$iw$$iw$$iw$$iw$$iw$$iw. error: symbol value i does not exist in scala.reflect.internal.FatalError: symbol value i does not exist in $line38.$read$$iw$$iw$$iw$$iw$$iw$$iw$$iw$$iw.
, а затем довольно большой трассировки стека, что приводит к «Заброшенный разбитого сессии» уведомления.
Я не могу сказать, является ли это проблемой для моей логики (вы просто не можете сращить тело функции, ссылающееся на закрытую переменную), или если это ошибка с новой реализацией. Сообщение об ошибке, конечно, может быть лучше. Это может усугубиться тем фактом, что я запускаю это на Repl.
Можно ли разделить функцию, отделив тело от закрытых терминов и переписать его, чтобы связать логику непосредственно с полученным деревом?
@KChalous Вы когда-нибудь могли исправить это сейчас, когда 'resetAllAttrs' был удален из Scala 2.11? У меня есть * точная * та же проблема, и я отчаянно пытаюсь ее исправить! –
@AndrewBate Согласно онлайн-документации, существует «resetLocalAttrs», который все еще существует, который должен охватывать большинство случаев. Не знаю, если это один из них, но это стоит того. Ссылка: http://docs.scala-lang.org/overviews/macros/changelog211.html – KChaloux
@AndrewBate и согласно проекту scalamacros на github, 'resetLocalAttrs' был переименован в' untypecheck'. Ссылка: https://github.com/scalamacros/resetallattrs – KChaloux