【问题标题】:Scala quasiquote macro example broken - type signatures offScala quasiquote 宏示例损坏 - 类型签名关闭
【发布时间】:2016-03-20 19:14:59
【问题描述】:

我从书 "Programming Scala" (2nd Edition) 中获取了这个 Scala quasiquote 示例

我收到此错误:https://issues.scala-lang.org/browse/SI-9711

类型推断显示“Trees#Tree”,但类型推断已关闭。

import scala.reflect.api.Trees // For Trees#Tree (TreeNode)
import scala.reflect.macros.blackbox._
import scala.reflect.runtime.universe._ // To use Scala runtime reflection

/**
  * Represents a macro invariant which is checked over the corresponding statements.
  * Example:
  * '''
  * var mustBeHello = "Hello"
  * invariant.execute(mustBeHello.equals("Hello")) {
  *   mustBeHello = "Goodbye"
  * }
  * // Throws invariant.InvariantFailure
  * '''
  */
object invariant {
  case class InvariantFailure(message: String) extends RuntimeException(message)

  type SyntaxTree = scala.reflect.runtime.universe.Tree

  type TreeNode = Trees#Tree // a syntax tree node that is in and of itself a tree

  // These two methods are the same, but one is a function call and the other is a macro function call
  def execute[RetType]              (myPredicate: => Boolean)(block: => RetType): RetType = macro executeMacro
  def executeMacro(context: Context)(myPredicate: SyntaxTree)(block: SyntaxTree) = {

    val predicateString: String = showCode(myPredicate) // turn this predicate into a String
    val q"..$statements" = block // make the block into a sequence of statements
    val myStatements: Seq[TreeNode] = statements // the statements are a sequence of SyntaxTreeNodes, each node a little Tree
    val invariantStatements = statements.flatMap { statement =>
        // Error here:
        val statementString: String = showCode(statement) /* Type mismatch, expected Tree, actual Trees#Tree */

        val message: String =
            s"FAILURE! $predicateString == false, for statement: " + statementString
        val tif: SyntaxTree =
            q"throw new metaprogramming.invariant.InvariantFailure($message)"
        val predicate2: SyntaxTree =
            q"if (false == $myPredicate) $tif"
        val toReturn: List[SyntaxTree] =
            List(q"{ val temp = $myStatements; $predicate2; temp };")
        toReturn
      }
    val tif: SyntaxTree =
        q"throw new metaprogramming.invariant.InvariantFailure($predicateString)"
    val predicate: SyntaxTree =
        q"if (false == $predicate) $tif"
    val toReturn: SyntaxTree =
        q"$predicate; ..$invariantStatements"
    toReturn
  }
}

^ 文档应该是不言自明的。类型推断为 Tree#Tree,但在示例代码中添加“:Tree#Tree”会导致编译出错:

[info] Compiling 2 Scala sources to /home/johnreed/sbtProjects/scala-trace-debug/target/scala-2.11/test-classes...
[error] /home/johnreed/sbtProjects/scala-trace-debug/src/test/scala/mataprogramming/invariant2.scala:30: type mismatch;
[error] found : TreeNode
error scala.reflect.api.Trees#Tree
[error] required: context.universe.Tree
[error] val exceptionMessage = s"FAILURE! $predicateAsString == false, for statement: " + showCode(statement)

我在 IntelliJ 中收到 "Type mismatch, expected Tree, actual Trees#Tree"

【问题讨论】:

  • 代码从何而来?它不在回购中。类型是依赖于路径的,这就是你使用c.Tree 等的原因。repo 编译。
  • @som-snytt - 此代码稍作修改。来自 repo 的未修改代码可以编译,但类型已关闭。见issues.scala-lang.org/browse/SI-9711
  • 您的代码不应该编译。当您的意思是 a.B. 时,您不能使用类型项目 A#B。我会试试你的票代码。

标签: scala intellij-idea macros scala-macros scala-quasiquotes


【解决方案1】:
[info] Compiling 2 Scala sources to /home/johnreed/sbtProjects/scala-trace-debug/target/scala-2.11/test-classes...
[error] /home/johnreed/sbtProjects/scala-trace-debug/src/test/scala/mataprogramming/invariant2.scala:30: type mismatch;
[error] found : TreeNode
error scala.reflect.api.Trees#Tree
[error] required: context.universe.Tree
[error] val exceptionMessage = s"FAILURE! $predicateAsString == false, for statement: " + showCode(statement)

这些类型确实很时髦。要么是 IntelliJ 弄乱了类型,要么是这个概念让我无法理解。

【讨论】:

    【解决方案2】:

    发现推断类型的“正常”方法是以下之一:

    • 使用:type询问REPL

    • 分配一个错误的类型并观察错误信息

    • 调用一个函数来显示事物的TypeTag

    例如,

    [error] /home/apm/clones/prog-scala-2nd-ed-code-examples/src/main/scala/progscala2/metaprogramming/invariant2.scala:25: type mismatch;
    [error]  found   : List[context.universe.Tree]
    [error]  required: Int
    [error]     val foo: Int = statements
    [error]                    ^
    

    这表明Tree 在上下文宇宙中是路径相关的。

    你不能只喂它任何一棵老树。

    this question 上的类似问题。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-02-11
      • 2021-06-09
      • 2021-11-06
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多