Я играл с новыми функциями макросов 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: значение символа i не существует в $line38.$read$$iw$$iw$$iw$$iw$$iw$$iw$$iw$$iw. ошибка: значение символа i не существует в scala.reflect.internal.FatalError: значение символа i не существует в $line38.$read$$iw$$iw$$iw$$iw$$iw$$iw$$iw $$вв.
А затем довольно большая трассировка стека, приводящая к уведомлению «Брошенный аварийный сеанс».
Я не могу сказать, является ли это проблемой моей логики (вы просто не можете соединить тело функции, которое ссылается на закрытую переменную), или это ошибка новой реализации. Сообщения об ошибках, безусловно, могли бы быть лучше. Это может усугубляться тем фактом, что я запускаю это на Repl.
Можно ли разделить функцию, отделив тело от закрытых терминов, и переписать ее, чтобы соединить логику непосредственно в результирующее дерево?
resetAllAttrs
был удален из Scala 2.11? У меня точно такая же проблема, и я отчаянно пытаюсь ее решить! - person Andrew Bate   schedule 16.01.2015resetLocalAttrs
, который должен охватывать большинство случаев. Не знаю, один ли это из них, но попробовать стоит. Ссылка: docs.scala-lang.org/overviews/macros/changelog211.html< /а> - person KChaloux   schedule 16.01.2015resetLocalAttrs
был переименован вuntypecheck
. Ссылка: github.com/scalamacros/resetallattrs - person KChaloux   schedule 16.01.2015untypecheck
достаточно. Однако, когда я пытаюсь сопоставить шаблонq"for ($i <- $collection) $body"
, мне нужен старыйresetAllAttrs
(по крайней мере, так кажется). Я использовал библиотеку resetAllAttrs для макросов Scala 2.11, и она работает, в то время как толькоuntypecheck
не работает, но я быстро сталкиваюсь с обычной проблемой, когдаresetAllAttrs
повреждает родительские деревья. - person Andrew Bate   schedule 16.01.2015resetAllAttrs
, но они удалили ее специально из-за упомянутой вами проблемы с повреждением дерева. Тем не менее, если вам это нужно, загляните на github.com/scalamacros/resetallattrs. - person KChaloux   schedule 16.01.2015